[toc]
## 舉個例子
**程序員為了找女朋友, 開始注意著裝和形象了...**
* 頭上帶一副方形黑框眼鏡。
* 上面是一件紫紅色針織毛衣,內套一件白色襯衫;
* 下面是一條卡其色休閑褲配一雙深色休閑皮鞋,加一條銀色針扣頭的黑色腰帶;
* 整體行裝雖不潮流,卻透露出一種工作人士的成熟、穩健和大氣!
* 人還是那個人, 不同的著裝, 體現不同的性格和形象.
## 代碼示例
```php
<?php
// 人
class Person {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function wear() {
echo "我的著裝是:" . PHP_EOL;
}
}
// 工程師
class Engineer extends Person {
private $skill;
public function __construct($name, $skill) {
parent::__construct($name);
$this->skill = $skill;
}
public function getSkill() {
return $this->skill;
}
public function wear() {
echo "我是" . $this->getSkill() . "工程師" . $this->getName() . PHP_EOL;
parent::wear();
}
}
// 教師
class Teacher extends Person {
private $title;
public function __construct($name, $title) {
parent::__construct($name);
$this->title = $title;
}
public function getTitle() {
return $this->title;
}
public function wear() {
echo "我是" . $this->getName() . $this->getTitle() . PHP_EOL;
parent::wear();
}
}
// 服裝裝飾器
class ClothingDecorator extends Person {
protected $decorated;
public function __construct($person) {
$this->decorated = $person;
}
public function wear() {
$this->decorated->wear();
}
}
// 休閑褲
class CasualPantDecorator extends ClothingDecorator {
public function __construct($person) {
parent::__construct($person);
}
public function wear() {
parent::wear();
echo "一條卡其色休閑褲" . PHP_EOL;
}
}
// 腰帶
class BeltDecorator extends ClothingDecorator {
public function __construct($person) {
parent::__construct($person);
}
public function wear() {
parent::wear();
echo "一條銀色針扣頭的黑色腰帶" . PHP_EOL;
}
}
// 皮鞋
class LeatherShoesDecorator extends ClothingDecorator {
public function __construct($person) {
parent::__construct($person);
}
public function wear() {
parent::wear();
echo "一雙深色休閑皮鞋" . PHP_EOL;
}
}
// 針織毛衣
class KnittedSweaterDecorator extends ClothingDecorator {
public function __construct($person) {
parent::__construct($person);
}
public function wear() {
parent::wear();
echo "一件紫紅色針織毛衣" . PHP_EOL;
}
}
// 白色襯衫
class WhiteShirtDecorator extends ClothingDecorator {
public function __construct($person) {
parent::__construct($person);
}
public function wear() {
parent::wear();
echo "一件白色襯衫" . PHP_EOL;
}
}
// 眼鏡
class GlassesDecorator extends ClothingDecorator {
public function __construct($person) {
parent::__construct($person);
}
public function wear() {
parent::wear();
echo "一副方形黑框眼鏡" . PHP_EOL;
}
}
$tony = new Engineer("Tony", "客戶端");
$pant = new CasualPantDecorator($tony);
$belt = new BeltDecorator($pant);
$shoes = new LeatherShoesDecorator($belt);
$shirt = new WhiteShirtDecorator($shoes);
$sweater = new KnittedSweaterDecorator($shirt);
$glasses = new GlassesDecorator($sweater);
$glasses->wear();
echo PHP_EOL;
$decorateTeacher = new GlassesDecorator(new WhiteShirtDecorator(new LeatherShoesDecorator(new Teacher("wells", "教授"))));
$decorateTeacher->wear();
```
```
D:\soft\php72\php.exe D:\project\php_dp\index.php
我是客戶端工程師Tony
我的著裝是:
一條卡其色休閑褲
一條銀色針扣頭的黑色腰帶
一雙深色休閑皮鞋
一件白色襯衫
一件紫紅色針織毛衣
一副方形黑框眼鏡
我是wells教授
我的著裝是:
一雙深色休閑皮鞋
一件白色襯衫
一副方形黑框眼鏡
Process finished with exit code 0
```
## 什么是裝飾模式?
> 動態地給一個對象增加一些額外的職責(Responsibility),就增加對象功能來說,裝飾模式比生成子類實現更為靈活。

## 模式特點
1. 可靈活地給一個對象增加職責或拓展功能
如上面的示例中,可任意地穿上自己想穿的衣服。不管穿上什么衣服,你還是那個你,但穿上不同的衣服你就會有不同的外表。
1. 可增加任意多個裝飾
你可以只穿一件衣服,也可以只穿一條褲子,也可以衣服和褲子各種搭配的穿,全隨你意!
1. 裝飾的順序不同,可能產生不同的效果
內褲穿在里面是正常人, 內褲外穿就變成了超人
## 優缺點
**裝飾模式的優點**:
1.使用裝飾模式來實現擴展比繼承更加靈活,它可以在不需要創造更多子類的情況下,將對象的功能加以擴展。
1. 可以動態地給一個對象附加更多的功能。
1. 可以用不同的裝飾器進行多重裝飾,裝飾的順序不同,可能產生不同的效果。
1. 裝飾類和被裝飾類可以獨立發展,不會相互耦合;裝飾模式相當于是繼承的一個替代模式。
**裝飾模式的缺點**:
1. 與繼承相比,用裝飾的方式拓展功能更加容易出錯,排錯也更困難。對于多次裝飾的對象,調試時尋找錯誤可能需要逐級排查,較為煩瑣。
## 應用場景
1. 有大量獨立的擴展,為支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。
1. 需要動態地增加或撤銷功能時。
1. 不能采用生成子類的方法進行擴充時,如類定義不能用于生成子類。