装饰器模式
简介
将对象放入特殊的装饰对象中从而使其获得新的行为
应用
java.io.InputStream
、OutputStream
、Reader
和Writer
的所有代码都有以自身类型的对象作为参数的构造函数。java.util.Collections
;checkedXXX()
、synchronizedXXX()
和unmodifiableXXX()
方法。javax.servlet.http.HttpServletRequestWrapper
和HttpServletResponseWrapper
类图
代码
-
问题:加入开了一个咖啡店,创建咖啡时可能往咖啡中加入不同类型的添加剂,例如牛奶,焦糖等,此时应该如何设计类
- 解决:将对应添加剂类型组合成新的子类,例如牛奶咖啡,焦糖咖啡,牛奶焦糖咖啡等
-
问题:如果有新的添加剂怎么办?如果添加剂过多可能造成类数量爆炸
- 解决:采用装饰模式,将添加剂作为装饰器装饰咖啡
// 咖啡类对应类图上最顶层的模板类 public abstract class Coffee { String description; public Coffee() { } public Coffee(String description) { this.description = description; } void getDescription() { System.out.println(description); }; } // 具体的咖啡类,对应被装饰的对象 public class CoffeeA extends Coffee{ public CoffeeA(String description) { super(description); } String description = "CoffeeA"; } // 装饰器超类,对应所有装饰器父类 public class CoffeeDecorator extends Coffee{ Coffee coffee = null; CoffeeDecorator(Coffee _coffee){ this.coffee = _coffee; } void getDescription() { this.coffee.getDescription(); }; } // 装饰器1 public class CoffeeDecorator1 extends CoffeeDecorator{ Coffee coffee = null; CoffeeDecorator1(Coffee _coffee){ super(_coffee); } void getDescription() { method1(); super.getDescription(); }; void method1() { System.out.println("咖啡中添加标号为1的添加剂"); } } // 装饰器2 public class CoffeeDecorator2 extends CoffeeDecorator{ Coffee coffee = null; CoffeeDecorator2(Coffee _coffee){ super(_coffee); } void getDescription() { method2(); super.getDescription(); }; void method2() { System.out.println("咖啡中添加标号为2的添加剂"); } } // 客户端 public class Client { public static void main(String[] args) { Coffee coffeeA = new CoffeeA("咖啡A"); coffeeA = new CoffeeDecorator1(coffeeA); coffeeA = new CoffeeDecorator2(coffeeA); coffeeA.getDescription(); } }
结果
咖啡中添加标号为2的添加剂
咖啡中添加标号为1的添加剂
咖啡A可以看到咖啡A 已经被两个添加剂修饰