装饰者模式
设计模式类型 : 结构性
概念 : 不改变原有类的对象 , 动态地将额外的功能附加到该对象上 ;
扩展对象功能 : 这种功能扩展方式比类继承更加灵活 ;
装饰者模式 : 移除类中的被装饰功能 , 将被装饰类简化 , 区分类的核心职责和装饰功能 ;
装饰者模式适用场景 :
① 功能扩展 : 为一个类扩展功能 , 为其添加额外的职责 ( 强调扩展 )
② 动态添加撤销功能 : 为一个对象动态添加额外功能 , 同时这些被添加的功能还能被动态撤销 ( 强调动态 )
**装饰者模式四个相关类 **
抽象构件类 : 这是核心 , 后面的三个类都需要继承该类
具体构件类 : 定义装饰者模式时用不到 , 在客户端被用户调用时 , 才初始化
抽象装饰者类 : 所有装饰者类的父类 , 需要继承抽象的被装饰者类,其持有一个构件类的实例
具体装饰者类 : 继承抽象的装饰者类 , 通过构造函数传入实体的构建类 , 其实现的抽象装饰者方法中 , 需要调用传入的实体对象的对应方法 , 然后加入额外的操作

例子
抽象构件类
1 2 3 4 5 6 7 8
| public abstract class Beverage { String description ="Unknown Beverage"; double cost; public String getDescription(){ return description; } public double getCost() { return cost;} }
|
具体构件类
1 2 3 4 5 6 7 8 9 10
| public class DarkRoast extends Beverage{ public DarkRoast(){ description = "DarkRoast"; cost = 1.05; } @Override public double getCost() { return cost; } }
|
1 2 3 4 5 6 7 8 9 10
| public class Espresso extends Beverage{ public Espresso(){ description = "Espresso"; cost = 1.99; } @Override public double getCost() { return cost; } }
|
1 2 3 4 5 6 7 8 9 10
| public class HouseBlend extends Beverage{ public HouseBlend(){ description = "House Blend Coffee"; cost = 0.89; } @Override public double getCost() { return cost; } }
|
抽象装饰者类
1 2 3 4 5 6 7 8
| public abstract class CondimentDecorator extends Beverage { Beverage beverage; public CondimentDecorator(Beverage beverage){ this.beverage = beverage; } public abstract String getDescription(); public abstract double getCost(); }
|
具体装饰者类
1 2 3 4 5 6 7 8 9 10 11 12
| public class Mocha extends CondimentDecorator{ public Mocha(Beverage beverage){ super(beverage); } public String getDescription(){ return beverage.getDescription() + ", Mocha"; } @Override public double getCost() { return 0.2 + beverage.getCost(); } }
|
1 2 3 4 5 6 7 8 9 10 11
| public class Soy extends CondimentDecorator{ public Soy(Beverage beverage) { super(beverage); } public String getDescription() { return beverage.getDescription() + ", Soy"; } public double getCost() { return 0.15 + beverage.getCost(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class Whip extends CondimentDecorator { public Whip(Beverage beverage) { super(beverage); } @Override public String getDescription() { return beverage.getDescription() + ", Whip"; } public double getCost() { return 0.10 + beverage.getCost(); } }
|
客户端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class StarbuzzCoffee { public static void main(String[] args) { Beverage beverage = new Espresso(); System.out.println(beverage.getDescription()+" $"+beverage.getCost());
Beverage beverage1 = new DarkRoast(); beverage1 = new Mocha(beverage1); beverage1 = new Soy(beverage1); System.out.println(beverage1.getDescription()+" $"+beverage1.getCost());
Beverage beverage2 = new HouseBlend(); beverage2 = new Whip(beverage2); beverage2 = new Whip(beverage2); System.out.println(beverage2.getDescription()+" $"+beverage2.getCost()); } }
|

**装饰者模式优点 **
① 扩展灵活 : 使用装饰者模式 , 比继承更加灵活 ; 使用装饰者模式扩展类功能 , 不会改变原来的类
② 排列组合 : 对装饰类进行各种排列组合 , 可实现不同的扩展功能
③ 开闭原则 : 装饰者模式符合开闭原则 , 被装饰的类 , 和装饰类相互独立 , 互不干扰
**装饰者模式缺点 **
① 程序复杂 : 需要编写更多的代码 , 生成更多的类 , 程序的复杂性增加了
② 动态 / 多层 装饰 : 动态 / 多层 装饰一个类时 , 程序更复杂
**继承与装饰者模式对比 **
① 继承复杂 : 使用继承扩展功能 , 需要生成很多子类 , 系统复杂性增加
② 继承静态 : 继承在编译时就要确定扩展的功能 , 是静态的
③ 装饰者模式动态扩展 : 装饰者模式可以动态扩展功能 , 可以在代码运行时扩展功能
**装饰者模式与代理模式 **
① 注重点 : 装饰者模式注重动态扩展功能 ; 代理模式注重对对象访问的控制 , 代理类对用户隐藏具体细节
② 实例对象的使用 : 装饰者模式将原始对象作为参数传递给装饰者类构造器 ; 代理模式中在代理类中创建实例对象
装饰者模式与适配器模式 : 二者都是包装模式
① 装饰者模式 : 装饰者模式中 , 装饰者和被装饰者实现相同的接口 , 或装饰者是被装饰者的子类 ;
② 适配器模式 : 适配器模式中 , 适配器和被适配的类有不同的接口 , 可能有部分接口重合 ;