GOF23设计模式之装饰模式(decorator)
一、装饰模式概述
(1)动态的为一个对象增加新的功能。
(2)装饰模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。
使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。
二、装饰模式实现细节
(1)Componen 抽象构件角色:
真实对象和装饰对象有相同的接口。这样,客户端就能够以真实对象相同的方式同装饰对象交互。
(2)ConcreteComponent 具体构件角色(真是角色):
IO 流中的FileInputStream、FileOutputStream
(3)Decorator 装饰角色:
持有一个抽象构件的引用。装饰对象接受所有客户端的请求,并把这些请求转发给真实的对象,这样就能在真实对象调用前后增加新的功能。
三、装饰模式情景导入
场景:设计一款可以增加任意功能的汽车,除了陆地上跑以外,还可以随意增加天上飞、水上游、自动驾驶等功能。
1 /** 2 * Component抽象构件角色 3 * @author CL 4 * 5 */ 6 public interface ICar { 7 void move(); 8 } 9 10 /** 11 * ConcreteComponent具体构件角色(真实角色) 12 * @author CL 13 * 14 */ 15 class Car implements ICar { 16 17 @Override 18 public void move() { 19 System.out.println("陆地上跑!"); 20 } 21 22 } 23 24 /** 25 * Decorator装饰角色 26 * @author CL 27 * 28 */ 29 class SuperCar implements ICar { 30 protected ICar car; 31 32 public SuperCar(ICar car) { 33 this.car = car; 34 } 35 36 @Override 37 public void move() { 38 car.move(); 39 } 40 } 41 42 /** 43 * ConcreteDecorator具体装饰角色 44 * 新增新的功能:天上飞 45 * @author CL 46 * 47 */ 48 class FlyCar extends SuperCar { 49 50 public FlyCar(ICar car) { 51 super(car); 52 } 53 54 public void fly() { 55 System.out.println("天上飞!"); 56 } 57 58 @Override 59 public void move() { 60 super.move(); 61 fly(); 62 } 63 64 } 65 66 /** 67 * ConcreteDecorator具体装饰角色 68 * 新增新的功能:水上游 69 * @author CL 70 * 71 */ 72 class WaterCar extends SuperCar { 73 74 public WaterCar(ICar car) { 75 super(car); 76 } 77 78 public void swim() { 79 System.out.println("水上游!"); 80 } 81 82 @Override 83 public void move() { 84 super.move(); 85 swim(); 86 } 87 88 } 89 90 /** 91 * ConcreteDecorator具体装饰角色 92 * 新增新的功能:人工智能 自动驾驶 93 * @author CL 94 * 95 */ 96 class AICar extends SuperCar { 97 98 public AICar(ICar car) { 99 super(car); 100 } 101 102 public void autoMove() { 103 System.out.println("自动驾驶!"); 104 } 105 106 @Override 107 public void move() { 108 super.move(); 109 autoMove(); 110 } 111 112 }
测试:
1 /** 2 * 测试装饰模式 3 * @author CL 4 * 5 */ 6 public class Client { 7 8 public static void main(String[] args) { 9 System.out.println("基本功能,陆地上跑-->"); 10 Car car = new Car(); 11 car.move(); 12 13 System.out.println("\n增加新的功能,天上飞-->"); 14 FlyCar flyCar = new FlyCar(car); 15 flyCar.move(); 16 17 System.out.println("\n增加新的功能,水上游-->"); 18 WaterCar waterCar = new WaterCar(car); 19 waterCar.move(); 20 21 System.out.println("\n增加新的功能,水上游, 自动驾驶-->"); 22 AICar aCar = new AICar(new WaterCar(car)); 23 aCar.move(); 24 25 System.out.println("\n增加新的功能,天上飞,水上游, 自动驾驶-->"); 26 AICar c = new AICar( 27 new WaterCar( 28 new FlyCar(car))); 29 c.move(); 30 } 31 32 }
控制台输出:
基本功能,陆地上跑--> 陆地上跑! 增加新的功能,天上飞--> 陆地上跑! 天上飞! 增加新的功能,水上游--> 陆地上跑! 水上游! 增加新的功能,水上游, 自动驾驶--> 陆地上跑! 水上游! 自动驾驶! 增加新的功能,天上飞,水上游, 自动驾驶--> 陆地上跑! 天上飞! 水上游! 自动驾驶!
四、装饰模式总结
装饰模式(Decorator)也叫做包装器模式(Wrapper)
装饰模式降低系统的耦合度,可以动态的增加或删除对象的职责,并使得需要装饰的具体构建类和具体装饰类可以独立变化,以便增加新的具体构建类和具体装饰类。
优点:
a. 扩展对象功能,比继承灵活,不会导致类个数急剧增加;
b. 可以对一个对象进行多次装饰,创造出不同行为的组合,得到功能更加强大的对象;
c. 具体构建类和具体装饰类可以独立变化,用户可以根据需要自己增加新的具体构件子类和具体装饰子类。
缺点:
a. 产生很多小对象,大量小对象占据内存,一定程度上影响性能;
b. 装饰模式易于出错,调试排查比较麻烦。
五、装饰模式实际开发应用场景
(1)IO 中输入流和输出流的设计
a. Componen 抽象构件角色:
IO 流中的InputStream、OutputStream、Reader、Writer
b. ConcreteComponen 具体构件角色:
IO 流中的FileInputStream、FileOutputStream
c. Decorator 装饰角色:
持有一个抽象构件的引用:IO 流中的FileInputStream、FileOutputStream
d. ConcreteDecorator 具体装饰角色:
负责给构件对象增加新的责任,IO 流中的BufferedInputStream、BufferedOutputStream
(2)Swing 包中图形界面构件功能;
(3)Servlet API 中提供了一个 request 对象的Decorator 设计模式的默认实现类,增强了 request 对象的功能;
(4)Struts2 中,request、response、session 对象的处理;
(5)…………