装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
实例如下:
package com.syy.test.decorator;
/**
* @ProjectName mp-test5
* @ClassName SchoolReport
* @Description 基础类 里面有两个方法
* @author 孙元元
* @date 2018年11月27日 下午5:16:56
*/
public abstract class SchoolReport {
abstract void report();
abstract void sign();
}
package com.syy.test.decorator;
/**
* @ProjectName mp-test5
* @ClassName FiveReport
* @Description 基础实现类
* @author 孙元元
* @date 2018年11月27日 下午5:17:27
*/
public class FiveReport extends SchoolReport{
@Override
public void report() {
System.out.println("本次考试的的成绩:");
System.out.println("语文:65分 ");
System.out.println("数学:60分 ");
System.out.println("体育:75分 ");
}
@Override
public void sign() {
System.out.println("家长签名: ");
}
}
package com.syy.test.decorator;
/**
* @ProjectName mp-test5
* @ClassName DecoratorReport
* @Description 装饰类 需要继承基础类 对基础类里的行为进行扩展
* @author 孙元元
* @date 2018年11月27日 下午5:15:13
*/
public abstract class DecoratorReport extends SchoolReport {
private SchoolReport schoolReport;
public DecoratorReport(SchoolReport schoolReport) {
super();
this.schoolReport = schoolReport;
}
public void report() {
schoolReport.report();
}
public void sign() {
schoolReport.sign();
}
}
package com.syy.test.decorator;
public class HighReport extends DecoratorReport {
public HighReport(SchoolReport schoolReport) {
super(schoolReport);
}
private void high() {
System.out.println("我们班的最高分:");
System.out.println("语文:75分 ");
System.out.println("数学:69分 ");
System.out.println("体育:80分 ");
}
@Override
public void report() {
high();
super.report();
}
}
package com.syy.test.decorator;
public class SortReport extends DecoratorReport {
public SortReport(SchoolReport schoolReport) {
super(schoolReport);
}
private void sort() {
System.out.println("本次考试我在班里的排名:19");
}
@Override
public void report() {
super.report();
sort();
}
}
package com.syy.test.decorator;
public class Father {
public static void main(String[] args) {
SchoolReport schoolReport = new FiveReport();
schoolReport = new HighReport(schoolReport);
schoolReport = new SortReport(schoolReport);
schoolReport.report();
schoolReport.sign();
}
}
运行结果:
我们班的最高分:
语文:75分
数学:69分
体育:80分
本次考试的的成绩:
语文:65分
数学:60分
体育:75分
本次考试我在班里的排名:19
家长签名:
装饰模式是对继承的有力补充,你要知道继承可不是万能的,继承可以解决实际的问题,但是在项目中你要考虑诸如易维护、易扩展、易复用等,而且在一些情况下(比如上面那个成绩单例子)你要是用继承就会增加很多了类,而且灵活性非常的差,那当然维护也不容易了,也就是说装饰模式可以替代继承,解决我们类膨胀的问题,你要知道继承是静态的给类增加功能,而装饰模式则是动态的给增加功能,你看上面的那个例子,我不想要 SortReport 这层的封装也很简单呀,直接在 Father 中去掉就可以了,如果你用继承就必须修改程序。
优点:
1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
缺点:
1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
设计原则:
1. 多组合,少继承。
利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
2. 类应设计的对扩展开放,对修改关闭。