概念
裝飾器模式(Decorator Pattern)允許為一個現有的物件添加新的功能,同時又不改變其結構。這種類型的設計模式屬於結構型模式,它是作為現有的類別的包裝。
這種模式創建了一個裝飾類,用來包裝原有的類,並在保持類方法簽名完整性的前提下,提供了額外的功能。
UML圖
角色
抽象組件角色(Component):定義一個對象接口,以規範準備接受附加責任的對象,即可以給這些對象動態地添加職責。
具體組件角色(ConcreteComponent) :被裝飾者,定義一個將要被裝飾增加功能的類別。可以為這個類別的物件添加一些職責
抽象裝飾器(Decorator):維持一個指向構件Component物件的實例,並定義一個與抽像元件角色Component介面一致的介面
具體裝飾器角色(ConcreteDecorator):向組件添加職責。
適用場景
需要動態的為一個物件新增功能,這些功能可以再動態的撤銷。
需要增加一些基本功能的排列組合而產生的非常大量的功能,從而使繼承關係變的不切實際。
當不能採用產生子類別的方法進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因為類別定義被隱藏,或類別定義不能用來產生子類別。
代碼
<?php header('Content-type:text/html;charset=utf-8'); /** * 装饰器模式 */ /** * Interface IComponent 组件对象接口 */ interface IComponent { public function display(); } /** * Class Person 待装饰对象 */ class Person implements IComponent { private $_name; /** * Person constructor. 构造方法 * * @param $name 对象人物名称 */ public function __construct($name) { $this->_name = $name; } /** * 实现接口方法 */ public function display() { echo "装扮者:{$this->_name}<br/>"; } } /** * Class Clothes 所有装饰器父类-服装类 */ class Clothes implements IComponent { protected $component; /** * 接收装饰对象 * * @param IComponent $component */ public function decorate(IComponent $component) { $this->component = $component; } /** * 输出 */ public function display() { if(!empty($this->component)) { $this->component->display(); } } } /** * 下面为具体装饰器类 */ /** * Class Sneaker 运动鞋 */ class Sneaker extends Clothes { public function display() { echo "运动鞋 "; parent::display(); } } /** * Class Tshirt T恤 */ class Tshirt extends Clothes { public function display() { echo "T恤 "; parent::display(); } } /** * Class Coat 外套 */ class Coat extends Clothes { public function display() { echo "外套 "; parent::display(); } } /** * Class Trousers 裤子 */ class Trousers extends Clothes { public function display() { echo "裤子 "; parent::display(); } } /** * 客户端测试代码 */ class Client { public static function test() { $zhangsan = new Person('张三'); $lisi = new Person('李四'); $sneaker = new Sneaker(); $coat = new Coat(); $sneaker->decorate($zhangsan); $coat->decorate($sneaker); $coat->display(); echo "<hr/>"; $trousers = new Trousers(); $tshirt = new Tshirt(); $trousers->decorate($lisi); $tshirt->decorate($trousers); $tshirt->display(); } } Client::test();
運行結果:
外套 運動鞋 裝扮者:張三
T卹 褲子 裝扮者:李四