裝飾模式可以實現動態的爲對象添加功能,是從一個對象外部來給對象添加功能。一般有兩種方式能夠實現給一個類或對象增長行爲: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源碼學習裏,歡迎訪問閱讀。