设计类应该对修改关闭,对扩展开放。
使用装饰者模式:
1.装饰者和被装饰者必须有相同的超类型。
2.可以用一个或多个装饰者包装一个对象。
3.装饰者和被装饰者拥有相同的超类型,所以可以使用装饰者的地方也可以使用装饰过的对象取代它。
4.装饰者可以在所委托的被装饰者的行为之前或者之后添加上自己的行为,达到装饰的目的。
5.对象可以在任何时候被装饰,所以可以在运行时动态的不限量的被装饰。
装饰者模式动态的将责任附加到对象上去,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。
UML类图
代码:
1 超类饮料接口 2 interface Beverage 3 { 4 public function cost(); 5 public function description(); 6 }
1 饮料类 2 class Tea implements Beverage 3 { 4 public function cost() 5 { 6 return 1.1; 7 } 8 9 public function description() 10 { 11 return 'green tea'; 12 } 13 } 14 15 class Coffe implements Beverage 16 { 17 public function cost() 18 { 19 return 2.2; 20 } 21 22 public function description() 23 { 24 return 'black coffe'; 25 } 26 }
调料类
1 class AddSalt implements Beverage 2 { 3 private $beverage; 4 5 public function __construct(Beverage $beverage) 6 { 7 $this -> beverage = $beverage; 8 } 9 10 public function cost() 11 { 12 return $this -> beverage -> cost() + 0.5; 13 } 14 15 public function description() 16 { 17 return 'Salt '.$this -> beverage -> description(); 18 } 19 } 20 21 class AddSugger implements Beverage 22 { 23 private $beverage; 24 25 public function __construct(Beverage $beverage) 26 { 27 $this -> beverage = $beverage; 28 } 29 30 public function cost() 31 { 32 return $this -> beverage -> cost() + 0.6; 33 } 34 35 public function description() 36 { 37 return 'Sugger '.$this -> beverage -> description(); 38 } 39 }
测试:
1 $tea = new Tea(); 2 $tea = new AddSugger($tea); 3 $tea = new AddSalt($tea); 4 print_r($tea -> description());
结果:
Salt Sugger green tea
如果需要其他调料,就可以不修改原有的代码来实现了。对修改关闭,对扩展开放。
虽然继承可以添加扩展,但不见得是达到弹性设计的最佳方式,组合和委托可用于在运动时添加新的行为。
过多的装饰者会导致设计中出现许多的小对象。会让程序变得复杂
有些代码会依赖于特定的类型。