装饰器模式
<h3>装饰器模式(Decorator Pattern)</h3>
<ul>
<li>允许向一个已有的对象添加新的功能或部分内容,同时又不改变其结构。是作为现有的类的一个包装。</li>
</ul>
<h3>为什么需要装饰器模式:</h3>
<ul>
<li>要对一个已有的对象添加新功能,又不想修改它原来的结构。</li>
<li>使用子类继承的方法去实现添加新功能,会不可避免地出现子类过多,继承链很长的情况。而且不少书籍都规劝我们竭力保持一个对象的父与子关系不超过3个。</li>
<li>装饰器模式,可以提供对对象内容快速非侵入式地修改。</li>
</ul>
<h3>简单实例</h3>
<ul>
<li>如果有一个游戏角色,他原来就是默认穿一件长衫。现在游戏改进了,觉得这个角色,除了穿一件长衫前,还可以在里面穿一件袍子,或是一件球衣。在外面穿一套盔甲或是宇航服。</li>
</ul>
<h2>代码示例</h2>
<pre><code class="language-PHP"><?php
/*游戏原来的角色类
class Person{
public function clothes(){
echo "长衫".PHP_EOL;
}
}
*/
//装饰器接口
interface Decorator
{
public function beforeDraw();
public function afterDraw();
}
//具体装饰器1-宇航员装饰
class AstronautDecorator implements Decorator
{
public function beforeDraw()
{
echo "穿上T恤".PHP_EOL;
}
function afterDraw()
{
echo "穿上宇航服".PHP_EOL;
echo "穿戴完毕".PHP_EOL;
}
}
//具体装饰器2-警察装饰
class PoliceDecorator implements Decorator{
public function beforeDraw()
{
echo "穿上警服".PHP_EOL;
}
function afterDraw()
{
echo "穿上防弹衣".PHP_EOL;
echo "穿戴完毕".PHP_EOL;
}
}
//被装饰者
class Person{
protected $decorators = array(); //存放装饰器
//添加装饰器
public function addDecorator(Decorator $decorator)
{
$this->decorators[] = $decorator;
}
//所有装饰器的穿长衫前方法调用
public function beforeDraw()
{
foreach($this->decorators as $decorator)
{
$decorator->beforeDraw();
}
}
//所有装饰器的穿长衫后方法调用
public function afterDraw()
{
$decorators = array_reverse($this->decorators);
foreach($decorators as $decorator)
{
$decorator->afterDraw();
}
}
//装饰方法
public function clothes(){
$this->beforeDraw();
echo "穿上长衫".PHP_EOL;
$this->afterDraw();
}
}
//警察装饰
$police = new Person;
$police->addDecorator(new PoliceDecorator);
$police->clothes();
//宇航员装饰
$astronaut = new Person;
$astronaut->addDecorator(new AstronautDecorator);
$astronaut->clothes();
//混搭风
$madman = new Person;
$madman->addDecorator(new PoliceDecorator);
$madman->addDecorator(new AstronautDecorator);
$madman->clothes();</code></pre>