场景
(本例子来自于设计模式之禅)
在上小学的时候学校每次期末发成绩都会让家长签字,而这都会让一些学生十分头疼的事情,如果直接给家长看成绩,成绩考的不好家长又会说我们,但是又不能直接改成绩,如何解决呢?有一个同学想到了一个好办法,我先不直接告诉家长成绩,我先说一些这次考试的一些其他数据,比如说每门课最高是多少分啊,我在班级的排名是多少啊,因为如果直接看成绩家长肯定是会跟满分比较的,如果班级最高分才得了80多分,那么这样肯定会比直接说家长会容易接受一些(自己也会少挨点打....);
实现起来,可以设计一个成绩相关的类,方法包括汇报成绩单,签字等,然后在实现一个子类,添加两个汇报最高分和排名的方法,这样家长看成绩时可以在内部先调用这两个方法再汇报成绩,这样这个问题是解决了,但是会出现更多的问题,比如,如果家长想先看成绩怎么办?之间的顺序怎么调整,如果又需要其他相关的数据怎么办?难道要继续实现更多的子类吗?那样的话光要调整顺序就需要很多的子类,别说提需求了,所以前人提出了装饰者模式解决了这个问题,具体就是将想要添加的额外数据继承自同一个类,叫做装饰者类,同时装饰者类是与具体操作的类(这里就指家长看成绩的类)继承自同一抽象类的,接下来装饰者类的每一个子类就负责一个装饰方法,比如最高成绩和排名就可以写在两个子类里面,装饰者模式重要的一点是每个子类要保存一个最原始的那个抽象类的对象,毕竟要指出来是要装饰哪个类的,这样之前说的类爆炸的问题就解决了.
定义
动态地给一个对象添加一些额外的职责
构成
- Component抽象构件:是一个接口或者抽象类,包含了最基本的方法,最核心的对象
- ConcreteComponent具体构件:抽象构件的实现,装饰的对象
- Decorator装饰角色:实现一个接口或者抽象方法,包含一个Component类的熟悉属性,作为装饰对象
- 具体装饰角色:可能会有多个,继承自Decorator,将所要装饰的不同的方法放进这些类中
测试
代码:
public class DecoratorPattern {
public static void main(String[] args) {
Component report;
report = new ConcreteComponent();
report = new ConcreteDecoratorA(report);
report = new ConcreteDecoratorB(report);
report.operate();
}
}
// 抽象 构件
abstract class Component {
abstract void operate();
}
// 具体构件
class ConcreteComponent extends Component {
@Override
void operate() {
System.out.println("原方法");
}
}
// 装饰类
class Decorator extends Component {
private Component component;
public Decorator(Component component) {
this.component = component;
}
@Override
void operate(){
this.component.operate();
}
}
// 具体装饰类A
class ConcreteDecoratorA extends Decorator {
public ConcreteDecoratorA(Component component) {
super(component);
}
// 装饰类A装饰方法
private void method2(){
System.out.println("ConcreteDecoratorA的装饰方法");
}
@Override void operate() {
this.method2();
super.operate();
}
}
//具体装饰类B
class ConcreteDecoratorB extends Decorator {
public ConcreteDecoratorB(Component component) {
super(component);
}
// 装饰类B装饰方法
private void method1(){
System.out.println("ConcreteDecoratorB的装饰方法");
}
@Override void operate() {
this.method1();
super.operate();
}
}
运行结果:
运行结果优缺点
优点
- 装饰类和被装饰类独立发展,不会互相耦合,也就是说Component不需要知道Decorator具体做了些什么,反过来也是一样
- 是继承关系的替代方案,无论有多少个修饰类,最后返回的结果还是Component对象
- 可以动态地扩展一些功能
缺点
- 如果层数太多,出现问题定位问题比较麻烦,如果问题出现在最底层的修饰类,那么我们要从最高层一直跟踪到最底层才会发现问题,修复时间比较长
感想
总的来说装饰者模式很多应用的场景是为了替代继承的,继承对于扩展和维护方面相对较复杂,尤其是业务上各种业务模块相类似,利用继承会出现类爆炸的情况,装饰者模式相对来说容易一些;而且对于新需求过来的时候装饰者模式也只需要增加装饰类就可以解决,继承的话还是会迭代更多的类层数.
网友评论