装饰器设计模式
装饰器模式就是在不改变原有对象的基础上,将功能附加在对象上,提供了比继承更有扩展性的方案,继承的替代方案,子类可拓展功能,相当于对一个对象可以创建出不同行为的组合,得到更强大的对象。
角色
- 抽象构件(Component)角色 :定义一个抽象接口以规范准备接收附加责任的对象。
- 具体构件(Concrete Component)角色 :实现抽象构件,通过装饰角色为其添加一些职责。
- 抽象装饰(Decorator)角色 : 继承或实现抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。
- 具体装饰(ConcreteDecorator)角色 :实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。
代码示例
想要清楚的了解装饰器代码的作用,用代码装饰器和不用代码装饰器来进行对比
我们要知道,装饰器的本质本身也是类增强和代理模式很像,或者说他就是另外一种特殊代理模式,具体区别我们后面会分析。
正常不用装饰器代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class Meal { public String getDescription() { return "饭"; }
public Integer getPrice() { return 5; } }
public class EggMeal extends Meal { public String getDescription() { return super.getDescription() + "+鸡蛋"; }
public Integer getPrice() { return 10 + super.getPrice(); } }
public class EggHumMeal extends EggMeal { @Override public String getDescription() { return super.getDescription() + "+火腿"; }
@Override public Integer getPrice() { return super.getPrice() + 3; } }
|
用装饰器模式
我们要知道,装饰器的角色有那些:抽象构件,目标构件、抽象装饰器、具体装饰器。
但是我们也要具体情况具体分析,不是什么一拿着就按照上面的这个套。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
|
public class Meal { String getDescription() { return "饭"; }
Integer getPrice() { return 5; } }
public abstract class Ingredients extends Meal { private Meal meal;
public Ingredients(Meal meal) { this.meal = meal; }
@Override String getDescription() { return this.meal.getDescription(); }
@Override Integer getPrice() { return this.meal.getPrice(); } }
public class Hum extends Ingredients { public Hum(Meal meal) { super(meal); }
@Override String getDescription() { return super.getDescription() + "火腿"; }
@Override Integer getPrice() { return super.getPrice() + 2; } }
public class Egg extends Ingredients { public Egg(Meal meal) { super(meal); }
@Override String getDescription() { return super.getDescription() + "鸡蛋"; }
@Override Integer getPrice() { return super.getPrice() + 3; } }
public static void main(String[] args) { Meal meal = new Meal(); System.out.println(meal.getDescription() + ":" + meal.getPrice() + "元");
meal = new Hum(meal); System.out.println(meal.getDescription() + ":" + meal.getPrice() + "元");
meal = new Egg(meal); System.out.println(meal.getDescription() + ":" + meal.getPrice() + "元");
Meal eggTwo = new Egg(meal); System.out.println(eggTwo.getDescription() + ":" + eggTwo.getPrice() + "元");
}
|
可以看到,使用装饰器模式的方法实现,与普通的继承方法实现,最大的区别就是一种配料只有一个类,而且在加配料的时候,也可以直接想加多少就加多少,不需要说一个鸡蛋一个类,两个鸡蛋也要创建一个类,这样可以带来比继承更加灵活的扩展功能,使用也更加方便。
总结
装饰器模式与代理模式对比:
参考文章
- 装饰器模式就是一种特殊的代理模式。
- 装饰器模式强调自身的功能扩展,用自己说了算的透明扩展,可动态定制的扩展;代理模式强调代理过程的控制。
- 获取目标对象构建的地方不同,装饰者是从外界传递进来的,可以通过构造方法传递;静态代理是在代理类内部创建,以此来隐藏目标对象。
适用场景:
- 用于扩展一个类的功能或者给一个类添加附加职责。
- 动态的给一个对象添加功能,这些功能同样也可以再动态的撤销。
优点:
- 装饰器是继承的有力补充,比继承灵活,不改变原有对象的情况下动态地给一个对象扩展功能,即插即用。
- 通过使用不同装饰类以及这些装饰类的排列组合,可实现不同效果。
- 装饰器完全遵守开闭原则。
缺点:
- 会出现更多的代码,更多的类,增加程序的复杂性。
- 动态装饰时,多层装饰会更复杂。