装饰模式可以实现动态的为对象添加功能,是从一个对象外部来给对象添加功能。一般有两种方式能够实现给一个类或对象增长行为:html
显然,为了扩展对象功能频繁修改父类或者派生子类这种方式并不可取。在面向对象的设计中,咱们应该尽可能使用对象组合,而不是对象继承来扩展和复用功能。装饰器模式就是基于对象组合的方式,能够很灵活的给对象添加所须要的功能。装饰器模式的本质就是动态组合。动态是手段,组合才是目的。总之,装饰模式是经过把复杂的功能简单化,分散化,而后在运行期间,根据须要来动态组合的这样一个模式。git
装饰模式(Decorator Pattern) :动态地给一个对象增长一些额外的职责(Responsibility),就增长对象功能来讲,装饰模式比生成子类实现更为灵活。其别名也能够称为包装器(Wrapper),与适配器模式的别名相同,但它们适用于不一样的场合。根据翻译的不一样,装饰模式也有人称之为“油漆工模式”,它是一种对象结构型模式。github
Component:组件对象的接口,能够给这些对象动态的添加职责;bash
ConcreteComponent:具体的组件对象,实现了组件接口。该对象一般就是被装饰器装饰的原始对象,能够给这个对象添加职责;app
Decorator:全部装饰器的父类,须要定义一个与Component接口一致的接口(主要是为了实现装饰器功能的复用,即具体的装饰器A能够装饰另一个具体的装饰器B,由于装饰器类也是一个Component),并持有一个Component对象,该对象其实就是被装饰的对象。若是不继承Component接口类,则只能为某个组件添加单一的功能,即装饰器对象不能再装饰其余的装饰器对象。学习
ConcreteDecorator:具体的装饰器类,实现具体要向被装饰对象添加的功能。用来装饰具体的组件对象或者另一个具体的装饰器对象。ui
1.Component抽象类, 能够给这些对象动态的添加职责this
abstract class Component
{
abstract public function operation();
}
复制代码
2.Component的实现类spa
class ConcreteComponent extends Component
{
public function operation()
{
echo __CLASS__ . '|' . __METHOD__ . "\r\n";
}
}
复制代码
3.装饰器的抽象类,维持一个指向组件对象的接口对象, 并定义一个与组件接口一致的接口翻译
abstract class Decorator extends Component
{
/**
* 持有Component的对象
*/
protected $component;
/**
* 构造方法传入
*/
public function __construct(Component $component)
{
$this->component = $component;
}
abstract public function operation();
}
复制代码
4.装饰器的具体实现类,向组件对象添加职责,beforeOperation(),afterOperation()为先后添加的职责。
class ConcreteDecoratorA extends Decorator
{
//在调用父类的operation方法的前置操做
public function beforeOperation()
{
echo __CLASS__ . '|' . __METHOD__ . "\r\n";
}
//在调用父类的operation方法的后置操做
public function afterOperation()
{
echo __CLASS__ . '|' . __METHOD__ . "\r\n";
}
public function operation()
{
$this->beforeOperation();
$this->component->operation();//这里能够选择性的调用父类的方法,若是不调用则至关于彻底改写了方法,实现了新的功能
$this->afterOperation();
}
}
class ConcreteDecoratorB extends Decorator
{
//在调用父类的operation方法的前置操做
public function beforeOperation()
{
echo __CLASS__ . '|' . __METHOD__ . "\r\n";
}
//在调用父类的operation方法的后置操做
public function afterOperation()
{
echo __CLASS__ . '|' . __METHOD__ . "\r\n";
}
public function operation()
{
$this->beforeOperation();
$this->component->operation();//这里能够选择性的调用父类的方法,若是不调用则至关于彻底改写了方法,实现了新的功能
$this->afterOperation();
}
}
复制代码
5.客户端使用装饰器
class Client
{
public function main()
{
$component = new ConcreteComponent();
$decoratorA = new ConcreteDecoratorA($component);
$decoratorB = new ConcreteDecoratorB($decoratorA);
$decoratorB->operation();
}
}
$client = new Client();
$client->main();
复制代码
6.运行结果
oncreteDecoratorB|ConcreteDecoratorB::beforeOperation
ConcreteDecoratorA|ConcreteDecoratorA::beforeOperation
ConcreteComponent|ConcreteComponent::operation
ConcreteDecoratorA|ConcreteDecoratorA::afterOperation
ConcreteDecoratorB|ConcreteDecoratorB::afterOperation
复制代码
本文已经收录在系列文章Laravel源码学习里,欢迎访问阅读。