### 定义
又叫装饰者模式。装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。
### 作用
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。。
### 使用场景
人们着装。
### 优、缺点
优点:
装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:
多层装饰比较复杂。
### 模式结构
(略)
### 示例类图
代理模式包含几个角色:
* Component:抽象组件角色,需定义一个对象接口,以规范准备接受附加责任的对象,即可以给这些对象动态地添加职责。
* ConcreteComponent:被装饰者,定义一个将要被装饰增加功能的类。可以给这个类的对象添加一些职责。
* Decorator:抽象装饰器,维持一个指向构件Component对象的实例,并定义一个与抽象组件角色Component接口一致的接口。
* ConcreteDecorator:具体装饰器角色,向组件添加职责。
:-: ![](https://box.kancloud.cn/b6f2bafd7514739ec370870030767292_482x424.bmp)
### 示例代码
* 抽象组件角色(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恤 裤子 装扮者:李四
```
* * * * *
### 注意事项
* 可代替继承,在不想增加很多子类的情况下扩展类。