🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 装饰模式 装饰(Decorator)模式:动态地给(具体构建的)对象增加一些职责,即在原有的基础上增加其额外的功能。 **主要优点有:** - 采用装饰模式扩展对象的功能比采用继承方式更加灵活。 - 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。 **主要缺点是:** 装饰模式增加了许多子类,如果过度使用会使程序变得很复杂。 特点:用来增强原有对象功能,依附于原有对象。 应用:用于需要对原有对象增加功能而不是完全覆盖的时候 ## 装饰模式的应用场景 其适用的应用场景,装饰模式通常在以下几种情况使用。 - 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极(final)类或者采用继承方式会产生大量的子类。 - 当需要通过对现有的一组基本功能进行排列组合而产生非常多的功能时,采用继承关系很难实现,而采用装饰模式却很好实现。 - 当对象的功能要求可以动态地添加,也可以再动态地撤销时。 例:其中最常见的就是一些游戏开发商,通过去做一些装备,例如武器,衣服,鞋子,戒指等等,来吸引玩家购买,穿在身上不仅好看,还带有额外属性。 #### 1. 模式的结构 装饰模式主要包含以下角色。 > 将具体构建实例对象通过析构或者普通方法传入具体装饰类中 1. 抽象构件(Component)角色:定义一个抽象接口以规范准备接收附加责任的对象。 2. 具体构件(Concrete Component)角色:实现(implements)抽象构件,通过装饰角色为其添加一些职责。 3. 抽象装饰(Decorator)角色:继承抽象构件,并包含具体构件的实例,可以通过其子类扩展具体构件的功能。 4. 具体装饰(ConcreteDecorator)角色:实现抽象装饰的相关方法,并给具体构件对象添加附加的责任。 ![](https://img.kancloud.cn/69/4d/694dd961ce5f4379466a88e9c118e7f4_525x540.png) ``` <pre class="calibre10">``` <span class="token">//抽象构建</span> interface <span class="token4">Component</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//具体构建</span> class <span class="token4">ConcreteComponent</span> implements <span class="token4">Component</span><span class="token3">{</span> <span class="token">//具体组件类</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span><span class="token3">}</span> <span class="token3">}</span> <span class="token">//抽象装饰</span> abstract class <span class="token4">Decorator</span> implements <span class="token4">Component</span><span class="token3">{</span> <span class="token">// 装饰角色 </span> protected $_component<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>Component $component<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>_component <span class="token1">=</span> $component<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>_component<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体装饰1</span> class <span class="token4">ConcreteDecoratorA</span> extends <span class="token4">Decorator</span> <span class="token3">{</span> <span class="token">// 具体装饰类A</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>Component $component<span class="token3">)</span> <span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">__construct</span><span class="token3">(</span>$component<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 调用装饰类的操作</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">addedOperationA</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 执行新增加的操作方法</span> <span class="token3">}</span> <span class="token">//添加新的抽象方法,上面在调用</span> public <span class="token5">function</span> <span class="token4">addedOperationA</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span>echo <span class="token2">'A加点酱油;'</span><span class="token3">;</span><span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体装饰2</span> class <span class="token4">ConcreteDecoratorB</span> extends <span class="token4">Decorator</span> <span class="token3">{</span> <span class="token">// 具体装饰类B</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>Component $component<span class="token3">)</span> <span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">__construct</span><span class="token3">(</span>$component<span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">addedOperationB</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">addedOperationB</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span>echo <span class="token2">"B加点辣椒;"</span><span class="token3">;</span><span class="token3">}</span> <span class="token3">}</span> <span class="token">// clients</span> $component <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteComponent</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $decoratorA <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteDecoratorA</span><span class="token3">(</span>$component<span class="token3">)</span><span class="token3">;</span> $decoratorB <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteDecoratorB</span><span class="token3">(</span>$decoratorA<span class="token3">)</span><span class="token3">;</span> $decoratorA<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//输出:A加点酱油;</span> echo <span class="token2">'<br>--------<br>'</span><span class="token3">;</span> $decoratorB<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//输出:A加点酱油;B加点辣椒;</span> ``` ``` 下面这个例子是典型装饰器模式的应用,特点是在不影响其他类的情况下动态添加其它具体装备类 ``` <pre class="calibre10">``` <span class="token">/** 构件接口类(抽象构件类) * interface IComponent */</span> interface <span class="token4">IComponent</span> <span class="token3">{</span> <span class="token5">function</span> <span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">/** 人物类(具体构建类) * Person */</span> Class <span class="token4">Person</span> implements <span class="token4">IComponent</span> <span class="token3">{</span> private $name<span class="token3">;</span> <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>$name<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>name <span class="token1">=</span> $name<span class="token3">;</span> <span class="token3">}</span> <span class="token5">function</span> <span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"{$this->name}当前装备:"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">/** 装备类(抽象装饰) * Equipment */</span> Class <span class="token4">Equipment</span> implements <span class="token4">IComponent</span> <span class="token3">{</span> protected $component<span class="token3">;</span> <span class="token5">function</span> <span class="token4">Decorator</span><span class="token3">(</span>IComponent $component<span class="token3">)</span> <span class="token3">{</span> <span class="token">// 动态添加 </span> $this<span class="token1">-</span><span class="token1">></span>component <span class="token1">=</span> $component<span class="token3">;</span> <span class="token3">}</span> <span class="token5">function</span> <span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> <span class="token5">if</span><span class="token3">(</span><span class="token1">!</span><span class="token4">empty</span><span class="token3">(</span>$this<span class="token1">-</span><span class="token1">></span>component<span class="token3">)</span><span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>component<span class="token1">-</span><span class="token1">></span><span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">/** 具体装备 武器类(具体装饰) * Weapon */</span> Class <span class="token4">Weapon</span> extends <span class="token4">Equipment</span> <span class="token3">{</span> <span class="token5">function</span> <span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> echo <span class="token2">"龙泉剑 "</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">/** 具体装备 戒指类(具体装饰) * Ring */</span> Class <span class="token4">Ring</span> extends <span class="token4">Equipment</span> <span class="token3">{</span> <span class="token5">function</span> <span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> echo <span class="token2">"复活戒指 "</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">/** 具体装备 鞋子类(具体装饰) * Shoes */</span> Class <span class="token4">Shoes</span> extends <span class="token4">Equipment</span> <span class="token3">{</span> <span class="token5">function</span> <span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> echo <span class="token2">"御风履 "</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">// 如果需要可以继续添加具体的装备 腰带 裤子 手镯 </span> <span class="token">// 创建人物 </span> $people <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Person</span><span class="token3">(</span><span class="token2">"战士"</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 武器 </span> $Weapon <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Weapon</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 戒指 </span> $Ring <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Ring</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 鞋子 </span> $Shoes <span class="token1">=</span> <span class="token5">new</span> <span class="token4">Shoes</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">// 动态添加函数 </span> $Weapon<span class="token1">-</span><span class="token1">></span><span class="token4">Decorator</span><span class="token3">(</span>$people<span class="token3">)</span><span class="token3">;</span> $Ring<span class="token1">-</span><span class="token1">></span><span class="token4">Decorator</span><span class="token3">(</span>$Weapon<span class="token3">)</span><span class="token3">;</span> $Shoes<span class="token1">-</span><span class="token1">></span><span class="token4">Decorator</span><span class="token3">(</span>$Ring<span class="token3">)</span><span class="token3">;</span> <span class="token">// 显示 </span> $Shoes<span class="token1">-</span><span class="token1">></span><span class="token4">Display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token">//输出结果:</span> 战士当前装备:龙泉剑 复活戒指 御风履 ``` ``` 游戏角色变身 ``` <pre class="calibre10">``` <span class="token">//抽象构件角色:莫莉卡</span> interface <span class="token4">Morrigan</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//具体构件角色:原身</span> class <span class="token4">original</span> implements <span class="token4">Morrigan</span> <span class="token3">{</span> private $img<span class="token1">=</span><span class="token2">"Morrigan0.jpg"</span><span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> echo <span class="token2">"《恶魔战士》中的莫莉卡·安斯兰"</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">setImage</span><span class="token3">(</span>$img<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>img<span class="token1">=</span>$img<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">display</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $src<span class="token1">=</span><span class="token2">"src/decorator/"</span><span class="token3">.</span>$this<span class="token1">-</span><span class="token1">></span>img<span class="token3">;</span> echo $src<span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//抽象装饰角色:变形</span> class <span class="token4">Changer</span> implements <span class="token4">Morrigan</span> <span class="token3">{</span> public $m<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>Morrigan $m<span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>m<span class="token1">=</span>$m<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">display</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>m<span class="token1">-</span><span class="token1">></span><span class="token4">display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体装饰角色:女妖</span> class <span class="token4">Succubus</span> extends <span class="token4">Changer</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>Morrigan $m<span class="token3">)</span> <span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">__construct</span><span class="token3">(</span>$m<span class="token3">)</span><span class="token3">;</span> echo <span class="token2">"《恶魔战士》中的莫莉卡·安斯兰变身女妖"</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">display</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setChanger</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//执行变身(替换形态图片)</span> public <span class="token5">function</span> <span class="token4">setChanger</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>m<span class="token1">-</span><span class="token1">></span><span class="token4">setImage</span><span class="token3">(</span><span class="token2">"Morrigan1.jpg"</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体装饰角色:少女</span> class <span class="token4">Girl</span> extends <span class="token4">Changer</span> <span class="token3">{</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>Morrigan $m<span class="token3">)</span> <span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">__construct</span><span class="token3">(</span>$m<span class="token3">)</span><span class="token3">;</span> echo <span class="token2">"《恶魔战士》中的莫莉卡·安斯兰之变身少女"</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">display</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">setChanger</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//执行变身(替换形态图片)</span> public <span class="token5">function</span> <span class="token4">setChanger</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>m<span class="token1">-</span><span class="token1">></span><span class="token4">setImage</span><span class="token3">(</span><span class="token2">"Morrigan2.jpg"</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> class <span class="token4">MorriganAensland</span> <span class="token3">{</span> public static <span class="token5">function</span> <span class="token4">main</span><span class="token3">(</span><span class="token3">)</span> <span class="token3">{</span> $m0<span class="token1">=</span><span class="token5">new</span> <span class="token4">original</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $m0<span class="token1">-</span><span class="token1">></span><span class="token4">display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $m1<span class="token1">=</span><span class="token5">new</span> <span class="token4">Succubus</span><span class="token3">(</span>$m0<span class="token3">)</span><span class="token3">;</span> $m1<span class="token1">-</span><span class="token1">></span><span class="token4">display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $m2<span class="token1">=</span><span class="token5">new</span> <span class="token4">Girl</span><span class="token3">(</span>$m0<span class="token3">)</span><span class="token3">;</span> $m2<span class="token1">-</span><span class="token1">></span><span class="token4">display</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> MorriganAensland<span class="token3">:</span><span class="token3">:</span><span class="token4">main</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> ``` ``` ## 装饰模式的扩展 装饰模式所包含的 4 个角色不是任何时候都要存在的,在有些应用环境下模式是可以简化的,如以下两种情况。 (1) 如果只有一个具体构件而没有抽象构件时,可以让抽象装饰继承具体构件,其结构图如图 4 所示。 ![](https://img.kancloud.cn/7d/57/7d57d24c22281e9a0b6e69284aff33e4_423x549.png) ``` <pre class="calibre10">``` <span class="token">//具体构件</span> class <span class="token4">ConcreteComponet</span><span class="token3">{</span> <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> echo <span class="token2">"原来的东西|"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//抽象装饰</span> class <span class="token4">Decorator</span> extends <span class="token4">ConcreteComponet</span><span class="token3">{</span> private $componet<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>ConcreteComponet $componet<span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>componet<span class="token1">=</span>$componet<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>componet<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体装饰1</span> class <span class="token4">ConcreteDecorator1</span> extends <span class="token4">Decorator</span><span class="token3">{</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">addedFunction</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">addedFunction</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> echo <span class="token2">"新增加的东西1|"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体装饰2</span> class <span class="token4">ConcreteDecorator2</span> extends <span class="token4">Decorator</span><span class="token3">{</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> parent<span class="token3">:</span><span class="token3">:</span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">addedFunction</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">addedFunction</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> echo <span class="token2">"新增加的东西2|"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">// clients</span> $concreteComponet <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteComponet</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $decorator1 <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteDecorator1</span><span class="token3">(</span>$concreteComponet<span class="token3">)</span><span class="token3">;</span> $decorator2 <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteDecorator2</span><span class="token3">(</span>$decorator1<span class="token3">)</span><span class="token3">;</span> $decorator1<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//输出:原来的东西|新增加的东西1|</span> echo <span class="token2">'<br>--------<br>'</span><span class="token3">;</span> $decorator2<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//输出:原来的东西|新增加的东西1|新增加的东西2|</span> ``` ``` (2) 如果只有一个具体装饰时,可以将抽象装饰和具体装饰合并,其结构图如图 5 所示。 ![](https://img.kancloud.cn/33/8f/338f8348238ffc5370011f9b46791c8f_521x340.png) ``` <pre class="calibre17">``` interface <span class="token4">Componet</span><span class="token3">{</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> <span class="token">//具体构件</span> class <span class="token4">ConcreteComponet</span> implements <span class="token4">Componet</span><span class="token3">{</span> <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> echo <span class="token2">"原来的东西|"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">//具体装饰与抽象装饰合并</span> class <span class="token4">ConcreteDecorator</span> extends <span class="token4">ConcreteComponet</span><span class="token3">{</span> private $componet<span class="token3">;</span> public <span class="token5">function</span> <span class="token4">__construct</span><span class="token3">(</span>ConcreteComponet $componet<span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>componet<span class="token1">=</span>$componet<span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> $this<span class="token1">-</span><span class="token1">></span>componet<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $this<span class="token1">-</span><span class="token1">></span><span class="token4">addedFunction</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> <span class="token3">}</span> public <span class="token5">function</span> <span class="token4">addedFunction</span><span class="token3">(</span><span class="token3">)</span><span class="token3">{</span> echo <span class="token2">"新增加的东西|"</span><span class="token3">;</span> <span class="token3">}</span> <span class="token3">}</span> <span class="token">// clients</span> $concreteComponet <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteComponet</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span> $decorator <span class="token1">=</span> <span class="token5">new</span> <span class="token4">ConcreteDecorator</span><span class="token3">(</span>$concreteComponet<span class="token3">)</span><span class="token3">;</span> $decorator<span class="token1">-</span><span class="token1">></span><span class="token4">operation</span><span class="token3">(</span><span class="token3">)</span><span class="token3">;</span><span class="token">//输出:原来的东西|新增加的东西|</span> ``` ```