场景描述:
煎饼果子,最普通是摊个煎饼,加个鸡蛋,加个薄脆等等
定义煎饼果子抽象基础类:
package com.decorator; public abstract class ChinesePancake { String description = "煎饼果子"; public String getDescription(){ return description; } public abstract double cost(); }
定义一个装饰者类:
package com.decorator; public abstract class ChinesePancakeDecorator extends ChinesePancake { public abstract String getDescription(); }
定义一个普通的煎饼果子
package com.decorator; public class CommonChinesePancake extends ChinesePancake { public CommonChinesePancake(){ description = "这是一个普通的煎饼果子"; } public double cost() { return 5.00; } }
加个鸡蛋
package com.decorator; public class EggDecorator extends ChinesePancakeDecorator { ChinesePancake chinesePancake; public EggDecorator(ChinesePancake chinesePancake) { this.chinesePancake=chinesePancake; } public String getDescription() { return chinesePancake.getDescription()+ ",加个鸡蛋"; } public double cost() { return 2.00 + chinesePancake.cost(); } }
加个薄脆
package com.decorator; public class BaocuiDecorator extends ChinesePancakeDecorator { ChinesePancake chinesePancake; public BaocuiDecorator(ChinesePancake chinesePancake) { this.chinesePancake=chinesePancake; } public String getDescription() { return chinesePancake.getDescription()+ ",加个薄脆"; } public double cost() { return 1.00 + chinesePancake.cost(); } }
开始要摊煎饼果子了:
package com.decorator; public class ChinesePancakeConsumer { public static void main(String args[]) { System.out.println("来个煎饼"); ChinesePancake chinesePancake=new CommonChinesePancake(); System.out.println(chinesePancake.getDescription()+":"+chinesePancake.cost()+"\n"); System.out.println("来个煎饼加一个鸡蛋"); ChinesePancake chinesePancake1=new CommonChinesePancake(); chinesePancake1=new EggDecorator(chinesePancake1); System.out.println(chinesePancake1.getDescription()+":"+chinesePancake1.cost()+"\n"); System.out.println("来个煎饼加一个鸡蛋再加一个薄脆"); ChinesePancake chinesePancake2=new CommonChinesePancake(); chinesePancake2=new EggDecorator(chinesePancake2); chinesePancake2=new BaocuiDecorator(chinesePancake2); System.out.println(chinesePancake2.getDescription()+":"+chinesePancake2.cost()+"\n"); } }
装饰者模式的应用场景:
1、 想透明并且动态地给对象增加新的职责的时候。
2、 给对象增加的职责,在未来存在增加或减少可能。
3、 用继承扩展功能不太现实的情况下,应该考虑用组合的方式。
装饰者模式的优点:
1、 通过组合而非继承的方式,实现了动态扩展对象的功能的能力。
2、 有效避免了使用继承的方式扩展对象功能而带来的灵活性差,子类无限制扩张的问题。
3、 充分利用了继承和组合的长处和短处,在灵活性和扩展性之间找到完美的平衡点。
4、 装饰者和被装饰者之间虽然都是同一类型,但是它们彼此是完全独立并可以各自独立任意改变的。
5、 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
装饰者模式的缺点:
1、 装饰链不能过长,否则会影响效率。
2、 因为所有对象都是Component,所以如果Component内部结构发生改变,则不可避免地影响所有子类(装饰者和被装饰者),也就是说,通过继承建立的关系总是脆弱地,如果基类改变,势必影响对象的内部,而通过组合(Decoator HAS A Component)建立的关系只会影响被装饰对象的外部特征。
3、只在必要的时候使用装饰者模式,否则会提高程序的复杂性,增加系统维护难度。