动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
装饰模式的组成
- Component抽象构件:一个接口或者是抽象类,就是定义最核心的对象,也就是最原始的对象;
- ConcreteComponent具体构件:是最核心、最原始、最基本的接口或抽象类的实现,要装饰的就是这个;
- Decorator装饰角色:一般是一个抽象类,用于实现接口或抽象方法,其中不一定有抽象的方法,但其属性里必然有一个private变量指向Component抽象构件;
- ConcreteDecorator具体装饰角色:把最核心、最原始、最基本的东西装饰成其他东西。
装饰模式的优点
- 装饰类和被装饰类可以独立发展,而不会相互耦合;
- 装饰模式是机场关系的一个替代方案;
- 装饰模式可以动态地扩展一个实现类的功能。
装饰模式的缺点
多层的装饰是比较复杂的,尽量减少装饰类的数量,以便降低系统的复杂度。
装饰模式的使用场景
- 需要扩展一个类的功能,或给一个类增加附加功能;
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销;
- 需要为一批的兄弟类进行改装或加装功能。
<?php
/**
* 装饰者模式
*/
namespace pattern;
interface Component {
public function operate();
}
class ConcreteComponent implements Component {
public function operate() {
echo 'Concrete Component operate' . PHP_EOL;
}
}
abstract class Decorator implements Component {
protected $component = null;
public function __construct(Component $component) {
$this->component = $component;
}
public function operate() {
$this->component->operate();
}
}
class ConcreteDecoratorA extends Decorator {
public function operate() {
parent::operate();
$this->_addOperate();
}
private function _addOperate() {
echo 'Concrete Decorator A add operation' . PHP_EOL;
}
}
class ConcreteDecoratorB extends Decorator {
public function operate() {
$this->_addOperate();
parent::operate();
}
private function _addOperate() {
echo 'Concrete Decorator B add operation' . PHP_EOL;
}
}
$component = new ConcreteComponent();
$decorator_a = new ConcreteDecoratorA($component);
$decorator_b = new ConcreteDecoratorB($component);
$decorator_a->operate();
echo str_repeat('-', 20) . PHP_EOL;
$decorator_b->operate();
$decorator_c = new ConcreteDecoratorB($decorator_b);
echo str_repeat('=', 20) . PHP_EOL;
$decorator_c->operate();
输出:
Concrete Component operate
Concrete Decorator A add operation
--------------------
Concrete Decorator B add operation
Concrete Component operate
====================
Concrete Decorator B add operation
Concrete Decorator B add operation
Concrete Component operate