什么是装饰器模式
装饰器模式(Decorator Pattern): 允许向一个已有的对象添加新的功能或部分内容,同时又不改变其结构。属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
为什么需要装饰器模式
- 我们要对一个已有的对象添加新功能,又不想修改它原来的结构。
- 使用子类继承的方法去实现添加新功能,会不可避免地出现子类过多,继承链很长的情况。而且不少书籍都规劝我们竭力保持一个对象的父与子关系不超过3个。
- 装饰器模式,可以提供对对象内容快速非侵入式地修改。
装饰器模式使用组合和委托,而不是使用继承来解决扩展问题。
PHP 代码实现
<?php
/**
* 功能接口
* Interface Decorator
*/
interface Decorator {
function beforeDo();
function afterDo();
}
/**
* 装饰器1
* Class Decorator1
*/
class Decorator1 implements Decorator
{
public function beforeDo()
{
echo '先去洗手<br/>';
}
public function afterDo()
{
echo '吃饱了,继续写代码<br/>';
}
}
/**
* 装饰器2
* Class Decorator2
*/
class Decorator2 implements Decorator
{
public function beforeDo()
{
echo '洗完手然后擦一下<br/>';
}
public function afterDo()
{
echo '代码上线,保佑无bug<br/>';
}
}
/**
* 被装饰的对象
* Class User
*/
class User
{
/**
* @var array 装饰器
*/
private $decorateArr = [];
/**
* 装饰对象的eat方法,此方法作为例子
*/
public function eat()
{
$this->beforeDo();
echo '<a style="color: red">开始吃饭</a><br/>';
$this->afterDo();
}
/**
* 添加装饰器
* @param Decorator $decorator
*/
public function addDecorate(Decorator $decorator)
{
$this->decorateArr[] = $decorator;
}
/**
* 遍历装饰器,调用装饰器方法
*/
public function beforeDo()
{
foreach ($this->decorateArr as $decorator)
{
$decorator->beforeDo();
}
}
/**
* 遍历装饰器,调用装饰器方法
*/
public function afterDo()
{
foreach ($this->decorateArr as $decorator)
{
$decorator->afterDo();
}
}
}
//=======================装饰器模式测试===============================
//实例化被装饰对象
$user = new User();
//添加装饰器
$user->addDecorate(new Decorator1());
$user->addDecorate(new Decorator2());
//调用方法
$user->eat();
//结果
//先去洗手
//洗完手然后擦一下
//开始吃饭
//吃饱了,继续写代码
//代码上线,保佑无bug