![](https://source.unsplash.com/random/1680x200) ## 装饰器模式(Decorator Pattern) **概念** 允许向一个已有的对象添加新的功能或部分内容,同时又不改变其结构。属于结构型模式,它是作为现有的类的一个包装。 **为什么需要装饰器模式** 1. 我们要对一个已有的对象添加新功能,又不想修改它原来的结构。 2. 使用子类继承的方法去实现添加新功能,会不可避免地出现子类过多,继承链很长的情况。而且不少书籍都规劝我们竭力保持一个对象的父与子关系不超过3个。 3. 装饰器模式,可以提供对对象内容快速非侵入式地修改。 **UML图** ![](https://img.kancloud.cn/f7/fa/f7fa9a0f8b59b34592506ce49c9f2f0c_643x546.jpg) **简单实例** 原本的对象和装饰共同的接口:奶茶接口 ``` // 奶茶接口 interface TeaInterface { /** * @Desc: 名称 * @return mixed */ public function name(); /** * @Desc: 价格 * @return mixed */ public function price(); } ``` 原本的对象:小麦奶茶 ``` /** * 小麦奶茶 * Class Wheat * @package app\common\repositories\decorator */ class Wheat extends TeaAbstract { public function name() { return '小麦奶茶'; } public function price() { return 12; } } ``` 原本的对象:蜂蜜柚子茶 ``` /** * 蜂蜜奶茶 * Class Honey * @package app\common\repositories\decorator */ class Honey extends TeaAbstract { public function name() { return '蜂蜜柚子茶'; } public function price() { return 10; } } ``` 装饰抽象类:DecoratorAbstract ``` abstract class DecoratorAbstract implements TeaInterface { // 奶茶实例 public $tea; public function __construct(TeaInterface $tea) { $this->tea = $tea; } } ``` 具体装饰类:加糖类 ``` class SugarDecorator extends DecoratorAbstract { public function name() { return $this->tea->name() . '加糖'; } public function price() { return $this->tea->price() + 1; } } ``` 具体装饰类:加奶类 ``` class MilkDecorator extends DecoratorAbstract { public function name() { return $this->tea->name() . '加奶'; } public function price() { return $this->tea->price() + 5; } } ``` 工作人员制作奶茶 ``` // 蜂蜜柚子茶 $tem = new Honey(); echo $tem->name().' | '.$tem->price()."<br/>"; // 蜂蜜柚子茶 + 糖 $suger = new SugarDecorator($tem); echo $suger->name().' | '.$suger->price()."<br/>"; // 小麦奶茶 $tem = new Wheat(); echo $tem->name().' | '.$tem->price()."<br/>"; // 小麦奶茶 + 奶 $suger = new MilkDecorator($tem); echo $suger->name().' | '.$suger->price()."<br/>"; ``` 成品输出 ``` 蜂蜜柚子茶 | 10 蜂蜜柚子茶加糖 | 11 小麦奶茶 | 12 小麦奶茶加奶 | 17 ```