动态(组合)地给一个对象增长一些额外的职责。就增长功能而言,Decorator 模式比生成子类(继承)更为灵活(消除重复代码 & 减小子类个数)。——《设计模式》GoFjava
若是在代码中出现以下相似代码:git
public class ClassA implements InterfaceA { InterfaceA a; // ... }
一个类既实现了 InterfaceA
接口,又包含 InterfaceA
字段,那么在这段代码的位置,几乎能够确定使用了装饰器模式。其中,实现 InterfaceA
是为了确保 ClassA
保留 InterfaceA
接口的规范,而包含 InterfaceA
字段是为了利用组合实现多态。github
装饰器,顾名思义,须要装饰谁?这个“谁”就是装饰器模式的主体,这个主体的具体实现通常会有规范它行为特质的接口(接口就是规范),咱们能够经过实现这个接口添加一个抽象装饰器(为了进一步的扩展装饰器的能力,因此这个装饰器为抽象的,或者称之为非叶子节点的,非最终使用的装饰器),当须要为主体对象扩展某些功能或者附加某些责任时,再建立具体的装饰器对象去继承上面的抽象装饰器,达到扩展主体对象功能或附加责任的目的。综上,代码设计思路以下:设计模式
明确须要装饰(扩展、附加责任)的主体对象如 ClassA
,示例代码以下:ide
public class ClassA { @Override public void eat() { System.out.println("吃饭"); } }
抽象出该主体对象的接口(规范)如 InterfaceA
,示例代码以下:测试
public interface InterfaceA { void eat(); }
建立抽象装饰器如 DecoratorA
,示例代码以下(装饰器模式显著代码特征):this
public abstract class DecoratorA implements InterfactA { protected InterfaceA interfaceA; }
建立具体的装饰器,用来扩展主体对象的功能,如 ConcreteDecoratorA
,示例代码以下:spa
public class ConcreteDecoratorA extends DecoratorA { public ConcreteDecoratorA (InterfaceA interfaceA) { this.interfaceA = interfaceA; } // 下方重写 `override` InterfaceA 中的方法,作功能增强 @Override public void eat() { // 功能增强 System.out.println("饭前洗手"); // 调用主体类方法,执行功能 this.interfaceA.eat(); // 功能增强 System.out.println("饭后洗手"); } }
测试示例代码以下:设计
@Test public void concreteDecoratorTest() { // 不使用装饰器 System.out.println("不使用装饰器:"); InterfaceA classA = new ClassA(); classA.eat(); System.out.println(); System.out.println("-------------------------------------------"); System.out.println(); // 使用装饰器 System.out.println("使用装饰器:"); InterfaceA concreteDecoratorA = new ConcreteDecoratorA(new ClassA()); concreteDecoratorA.eat(); }
输出以下所示:code
不使用装饰器: 吃饭 ------------------------------------------- 使用装饰器: 饭前洗手 吃饭 饭后洗手
模拟小明“吃饭”和“找对象”场景: