decorator pattern -- 装饰模式
Decorator,装饰模式
就是使“对象功能的扩展”能够根据需要来动态地实现,同时可以避免“扩展功能的增多”导致子类数量急剧增多,从而使得任何“功能扩展变化”所产生的负面影响降为最低。
Decorator提供了一种给类增加职责的方法,不是通过继承实现,而是组合。
举例,一辆汽车
1 class car 2 { 3 public: 4 virtual void turnLeft( )=0; 5 virtual void turnRight( )=0; 6 virtual void goBack( )=0; 7 virtual void goAhead( )=0; 8 //制动距离 9 virtual void getDistance( ){...} 10 protected: 11 int speed; 12 };
有三两不同排量的车,那么对应它们操作细节也有些不同
那么我们会理所当然的继承上面抽象类car。
1 class car2L:public car 2 { 3 public: 4 virtual void turnLeft( ){...} 5 virtual void turnRight( ){...} 6 virtual void goBack( ){...} 7 virtual void goAhead( ){...} 8 virtual void getDistance( ){...} 9 protected: 10 static const int maxSpeed; 11 }; 12 const int car2L::maxSpeed=450; 13 14 class car1.8L:public car 15 { 16 public: 17 virtual void turnLeft( ){...} 18 virtual void turnRight( ){...} 19 virtual void goBack( ){...} 20 virtual void goAhead( ){...} 21 virtual void getDistance( ){...} 22 protected: 23 static const int maxSpeed; 24 }; 25 const int car1.8L::maxSpeed=400; 26 27 class car1.5L:public car 28 { 29 public: 30 virtual void turnLeft( ){...} 31 virtual void turnRight( ){...} 32 virtual void goBack( ){...} 33 virtual void getAhead( ){...} 34 virtual void getDistance( ){...} 35 protected: 36 static const int maxSpeed; 37 } 38 const int car1.5L::maxSpeed=350;
那么现在又多出了3个汽车品牌:Audi,Benz,Ferrari那么又会在原来基础上增加功能
1 class car2LAudi:public car2L 2 { 3 public: 4 virtual void turnLeft( ){...} 5 virtual void turnRight( ){...} 6 virtual void goBack( ){...} 7 virtual void goAhead( ){...} 8 virtual void getDistance( ){...} 9 ... 10 protected: 11 static const int maxSpeed; 12 }; 13 const int car2LAudi::maxSpeed=480; 14 15 class car1.8LAudi:public car1.8L 16 { 17 public: 18 virtual void turnLeft( ){...} 19 virtual void turnRight( ){...} 20 virtual void goBack( ){...} 21 virtual void goAhead( ){...} 22 virtual void getDistance( ){...} 23 ... 24 protected: 25 static const int maxSpeed; 26 }; 27 const int car1.8LAudi::maxSpeed=430; 28 29 class car1.5LAudi:public car1.5L 30 { 31 public: 32 virtual void turnLeft( ){...} 33 virtual void turnRight( ){...} 34 virtual void goBack( ){...} 35 virtual void getAhead( ){...} 36 virtual void getDistance( ){...} 37 ... 38 protected: 39 static const int maxSpeed; 40 } 41 const int car1.5LAudi::maxSpeed=380; 42 43 class car2LBenz:public car2L 44 { 45 public: 46 virtual void turnLeft( ){...} 47 virtual void turnRight( ){...} 48 virtual void goBack( ){...} 49 virtual void goAhead( ){...} 50 virtual void getDistance( ){...} 51 ... 52 protected: 53 static const int maxSpeed; 54 }; 55 const int car2LBenz::maxSpeed=450; 56 57 class car1.8LBenz:public car1.8L 58 { 59 public: 60 virtual void turnLeft( ){...} 61 virtual void turnRight( ){...} 62 virtual void goBack( ){...} 63 virtual void goAhead( ){...} 64 virtual void getDistance( ){...} 65 ... 66 protected: 67 static const int maxSpeed; 68 }; 69 const int car1.8LBenz::maxSpeed=400; 70 71 class car1.5LBenz:public car1.5L 72 { 73 public: 74 virtual void turnLeft( ){...} 75 virtual void turnRight( ){...} 76 virtual void goBack( ){...} 77 virtual void getAhead( ){...} 78 virtual void getDistance( ){...} 79 .. 80 protected: 81 static const int maxSpeed; 82 } 83 const int car1.5LBenz::maxSpeed=350; 84 85 class car2LAudi:public car2L 86 { 87 public: 88 virtual void turnLeft( ){...} 89 virtual void turnRight( ){...} 90 virtual void goBack( ){...} 91 virtual void goAhead( ){...} 92 virtual void getDistance( ){...} 93 ... 94 protected: 95 static const int maxSpeed; 96 }; 97 const int car2LAudi::maxSpeed=480; 98 99 class car1.8LAudi:public car1.8L 100 { 101 public: 102 virtual void turnLeft( ){...} 103 virtual void turnRight( ){...} 104 virtual void goBack( ){...} 105 virtual void goAhead( ){...} 106 virtual void getDistance( ){...} 107 ... 108 protected: 109 static const int maxSpeed; 110 }; 111 const int car1.8LAudi::maxSpeed=430; 112 113 class car1.5LAudi:public car1.5L 114 { 115 public: 116 virtual void turnLeft( ){...} 117 virtual void turnRight( ){...} 118 virtual void goBack( ){...} 119 virtual void getAhead( ){...} 120 virtual void getDistance( ){...} 121 ... 122 protected: 123 static const int maxSpeed; 124 } 125 const int car1.5LAudi::maxSpeed=380; 126 127 class car2LFerrari:public car2L 128 { 129 public: 130 virtual void turnLeft( ){...} 131 virtual void turnRight( ){...} 132 virtual void goBack( ){...} 133 virtual void goAhead( ){...} 134 virtual void getDistance( ){...} 135 ... 136 protected: 137 static const int maxSpeed; 138 }; 139 const int car2LFerrari::maxSpeed=550; 140 141 class car1.8LFerraripublic car1.8L 142 { 143 public: 144 virtual void turnLeft( ){...} 145 virtual void turnRight( ){...} 146 virtual void goBack( ){...} 147 virtual void goAhead( ){...} 148 virtual void getDistance( ){...} 149 ... 150 protected: 151 static const int maxSpeed; 152 }; 153 const int car1.8LFerrari::maxSpeed=500; 154 155 class car1.5LFerrari:public car1.5L 156 { 157 public: 158 virtual void turnLeft( ){...} 159 virtual void turnRight( ){...} 160 virtual void goBack( ){...} 161 virtual void getAhead( ){...} 162 virtual void getDistance( ){...} 163 .. 164 protected: 165 static const int maxSpeed; 166 } 167 const int car1.5LFerrari::maxSpeed=450;
如果这里在做一个分类高档,中档,抵挡,继承上面各类,那么又需要写27个类。如果中间我们需要增加任何一个类的品种,都会增加对应的子类。上面有这么类原因是,准备好所有需要用到的类,必须在代码编译之前准备好。
上描述的问题根源在于我们过度使用了继承来扩展对象的功能,由于继承为类型引入的静态特质(必须在编译之前将所有类准备好),使得这种扩展方式缺乏灵活性;并且随着子类和扩展品种的增多,各种子类和扩展功能组合导致子类的数量以几何级数方式增长,以至代码难以维护。
装饰模式则是相对于上面“静态”为“动态”。
例如我们在上面基础上通过使用装饰模式加品牌。
1 class car 2 {}; 3 class car2L:public car 4 {}; 5 class car1.8L:public car 6 {} 7 class car1.5L:public car 8 {} 9 class decorator:public car 10 { 11 ... 12 ... 13 protected: 14 car * car; 15 }; 16 class AudiDecorator:public decorator 17 { 18 public: 19 virtual void turnLeft( ) 20 { 21 ... 22 增加有这个品牌的变化代码 23 } 24 ... 25 }; 26 class BenzDecorator:public decorator 27 { 28 public: 29 virtual void turnLeft( ) 30 { 31 ... 32 增加有这个品牌的变化代码 33 } 34 ... 35 }; 36 class FerrariDecorator:public decorator 37 { 38 public: 39 virtual void turnLeft( ) 40 { 41 ... 42 增加有这个品牌的变化代码 43 } 44 ... 45 }; 46 47 int main( int argc,char ** argv) 48 { 49 car2L * c=new car2L( ); 50 //相当于动态构造奔驰排量2L的车,相当于原先的car2LBenz类 51 BenzDecorator b=new BenzDecorator(c); 52 b->turnLeft( ); 53 b->turnRight( ); 54 ... 55 //相当于动态构造法拉利排量2L的车,相当于原先的car2LFerrari类 56 FerrariDecorator f=new FerrariDecorator(c); 57 f->turnLeft( ); 58 f->turnRight( ); 59 ... 60 return 0; 61 }