### 定義
又叫裝飾者模式。裝飾模式是在不必改變原類文件和使用繼承的情況下,動態地擴展一個對象的功能。它是通過創建一個包裝對象,也就是裝飾來包裹真實的對象。
### 作用
這種模式創建了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。。
### 使用場景
人們著裝。
### 優、缺點
優點:
裝飾類和被裝飾類可以獨立發展,不會相互耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動態擴展一個實現類的功能。
缺點:
多層裝飾比較復雜。
### 模式結構
(略)
### 示例類圖
代理模式包含幾個角色:
* Component:抽象組件角色,需定義一個對象接口,以規范準備接受附加責任的對象,即可以給這些對象動態地添加職責。
* ConcreteComponent:被裝飾者,定義一個將要被裝飾增加功能的類。可以給這個類的對象添加一些職責。
* Decorator:抽象裝飾器,維持一個指向構件Component對象的實例,并定義一個與抽象組件角色Component接口一致的接口。
* ConcreteDecorator:具體裝飾器角色,向組件添加職責。
:-: 
### 示例代碼
* 抽象組件角色(Component)
```
/**
* Interface IComponent 組件對象接口
*/
interface IComponent
{
public function display();
}
```
* 被裝飾者(ConcreteComponent)
```
/**
* 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/>";
}
}
```
* 抽象裝飾器(Decorator)
```
/**
* 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();
}
}
}
```
* 抽象裝飾器(Decorator)
```
/**
* 下面為具體裝飾器類
*/
/**
* 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 main($argv)
{
$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::main($argv);
```
* 運行結果
```
外套 運動鞋 裝扮者:張三
T恤 褲子 裝扮者:李四
```
* * * * *
### 注意事項
* 可代替繼承,在不想增加很多子類的情況下擴展類。