摘要:通常有兩種方式可以實(shí)現(xiàn)給一個(gè)類或?qū)ο笤黾有袨槔^承機(jī)制,使用繼承機(jī)制是給現(xiàn)有類添加功能的一種有效途徑,通過繼承一個(gè)現(xiàn)有類可以使得子類在擁有自身方法的同時(shí)還擁有父類的方法。
裝飾模式 (Decorator Pattern)
裝飾模式能夠?qū)崿F(xiàn)動(dòng)態(tài)的為對(duì)象添加功能,是從一個(gè)對(duì)象外部來給對(duì)象添加功能。通常有兩種方式可以實(shí)現(xiàn)給一個(gè)類或?qū)ο笤黾有袨椋?/p>
繼承機(jī)制,使用繼承機(jī)制是給現(xiàn)有類添加功能的一種有效途徑,通過繼承一個(gè)現(xiàn)有類可以使得子類在擁有自身方法的同時(shí)還擁有父類的方法。但是這種方法是靜態(tài)的,用戶不能控制增加行為的方式和時(shí)機(jī)。
組合機(jī)制,即將一個(gè)類的對(duì)象嵌入另一個(gè)對(duì)象中,由另一個(gè)對(duì)象來決定是否調(diào)用嵌入對(duì)象的行為以便擴(kuò)展自己的行為,我們稱這個(gè)嵌入的對(duì)象為裝飾器(Decorator)
顯然,為了擴(kuò)展對(duì)象功能頻繁修改父類或者派生子類這種方式并不可取。在面向?qū)ο蟮脑O(shè)計(jì)中,我們應(yīng)該盡量使用對(duì)象組合,而不是對(duì)象繼承來擴(kuò)展和復(fù)用功能。裝飾器模式就是基于對(duì)象組合的方式,可以很靈活的給對(duì)象添加所需要的功能。裝飾器模式的本質(zhì)就是動(dòng)態(tài)組合。動(dòng)態(tài)是手段,組合才是目的??傊b飾模式是通過把復(fù)雜的功能簡單化,分散化,然后在運(yùn)行期間,根據(jù)需要來動(dòng)態(tài)組合的這樣一個(gè)模式。
裝飾模式定義裝飾模式(Decorator Pattern) :動(dòng)態(tài)地給一個(gè)對(duì)象增加一些額外的職責(zé)(Responsibility),就增加對(duì)象功能來說,裝飾模式比生成子類實(shí)現(xiàn)更為靈活。其別名也可以稱為包裝器(Wrapper),與適配器模式的別名相同,但它們適用于不同的場(chǎng)合。根據(jù)翻譯的不同,裝飾模式也有人稱之為“油漆工模式”,它是一種對(duì)象結(jié)構(gòu)型模式。
裝飾模式的優(yōu)點(diǎn)裝飾模式與繼承關(guān)系的目的都是要擴(kuò)展對(duì)象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
可以通過一種動(dòng)態(tài)的方式來擴(kuò)展一個(gè)對(duì)象的功能,通過配置文件可以在運(yùn)行時(shí)選擇不同的裝飾器,從而實(shí)現(xiàn)不同的行為。
通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創(chuàng)造出很多不同行為的組合??梢允褂枚鄠€(gè)具體裝飾類來裝飾同一對(duì)象,得到功能更為強(qiáng)大的對(duì)象。
模式結(jié)構(gòu)和說明聚合關(guān)系用一條帶空心菱形箭頭的直線表示,上圖表示Component聚合到Decorator上,或者說Decorator由Component組成。
繼承關(guān)系用一條帶空心箭頭的直接表示
看懂UML類圖請(qǐng)看這個(gè)文檔
Component:組件對(duì)象的接口,可以給這些對(duì)象動(dòng)態(tài)的添加職責(zé);
ConcreteComponent:具體的組件對(duì)象,實(shí)現(xiàn)了組件接口。該對(duì)象通常就是被裝飾器裝飾的原始對(duì)象,可以給這個(gè)對(duì)象添加職責(zé);
Decorator:所有裝飾器的父類,需要定義一個(gè)與Component接口一致的接口(主要是為了實(shí)現(xiàn)裝飾器功能的復(fù)用,即具體的裝飾器A可以裝飾另外一個(gè)具體的裝飾器B,因?yàn)檠b飾器類也是一個(gè)Component),并持有一個(gè)Component對(duì)象,該對(duì)象其實(shí)就是被裝飾的對(duì)象。如果不繼承Component接口類,則只能為某個(gè)組件添加單一的功能,即裝飾器對(duì)象不能再裝飾其他的裝飾器對(duì)象。
ConcreteDecorator:具體的裝飾器類,實(shí)現(xiàn)具體要向被裝飾對(duì)象添加的功能。用來裝飾具體的組件對(duì)象或者另外一個(gè)具體的裝飾器對(duì)象。
裝飾器的示例代碼1.Component抽象類, 可以給這些對(duì)象動(dòng)態(tài)的添加職責(zé)
abstract class Component { abstract public function operation(); }
2.Component的實(shí)現(xiàn)類
class ConcreteComponent extends Component { public function operation() { echo __CLASS__ . "|" . __METHOD__ . " "; } }
3.裝飾器的抽象類,維持一個(gè)指向組件對(duì)象的接口對(duì)象,?并定義一個(gè)與組件接口一致的接口
abstract class Decorator extends Component { /** * 持有Component的對(duì)象 */ protected $component; /** * 構(gòu)造方法傳入 */ public function __construct(Component $component) { $this->component = $component; } abstract public function operation(); }
4.裝飾器的具體實(shí)現(xiàn)類,向組件對(duì)象添加職責(zé),beforeOperation(),afterOperation()為前后添加的職責(zé)。
class ConcreteDecoratorA extends Decorator { //在調(diào)用父類的operation方法的前置操作 public function beforeOperation() { echo __CLASS__ . "|" . __METHOD__ . " "; } //在調(diào)用父類的operation方法的后置操作 public function afterOperation() { echo __CLASS__ . "|" . __METHOD__ . " "; } public function operation() { $this->beforeOperation(); $this->component->operation();//這里可以選擇性的調(diào)用父類的方法,如果不調(diào)用則相當(dāng)于完全改寫了方法,實(shí)現(xiàn)了新的功能 $this->afterOperation(); } } class ConcreteDecoratorB extends Decorator { //在調(diào)用父類的operation方法的前置操作 public function beforeOperation() { echo __CLASS__ . "|" . __METHOD__ . " "; } //在調(diào)用父類的operation方法的后置操作 public function afterOperation() { echo __CLASS__ . "|" . __METHOD__ . " "; } public function operation() { $this->beforeOperation(); $this->component->operation();//這里可以選擇性的調(diào)用父類的方法,如果不調(diào)用則相當(dāng)于完全改寫了方法,實(shí)現(xiàn)了新的功能 $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.運(yùn)行結(jié)果
oncreteDecoratorB|ConcreteDecoratorB::beforeOperation ConcreteDecoratorA|ConcreteDecoratorA::beforeOperation ConcreteComponent|ConcreteComponent::operation ConcreteDecoratorA|ConcreteDecoratorA::afterOperation ConcreteDecoratorB|ConcreteDecoratorB::afterOperation裝飾模式需要注意的問題
一個(gè)裝飾類的接口必須與被裝飾類的接口保持相同,對(duì)于客戶端來說無論是裝飾之前的對(duì)象還是裝飾之后的對(duì)象都可以一致對(duì)待。
盡量保持具體組件類ConcreteComponent的輕量,不要把主邏輯之外的輔助邏輯和狀態(tài)放在具體組件類中,可以通過裝飾類對(duì)其進(jìn)行擴(kuò)展。 如果只有一個(gè)具體組件類而沒有抽象組件類,那么抽象裝飾類可以作為具體組件類的直接子類。
適用環(huán)境需要在不影響組件對(duì)象的情況下,以動(dòng)態(tài)、透明的方式給對(duì)象添加職責(zé)。
當(dāng)不能采用繼承的方式對(duì)系統(tǒng)進(jìn)行擴(kuò)充或者采用繼承不利于系統(tǒng)擴(kuò)展和維護(hù)時(shí)可以考慮使用裝飾類。
本文已經(jīng)收錄在系列文章Laravel源碼學(xué)習(xí)里,歡迎訪問閱讀。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/28699.html
摘要:定義裝飾模式力圖解決的問題是過度使用了繼承來擴(kuò)展對(duì)象的功能。裝飾模式是類繼承的另外一種選擇,類繼承在編譯時(shí)候增加行為,而裝飾模式是在運(yùn)行時(shí)增加行為。 The Decorator Pattern is a design pattern that allows behavior to be added to an individual object, either staticall...
摘要:然后在創(chuàng)建一個(gè)抽象的類,該類也實(shí)現(xiàn)了接口,并且持有一個(gè)類的對(duì)象。第四步創(chuàng)建具體的裝飾器類,該類繼承了類。第五步使用裝飾對(duì)象。 原文鏈接譯者:smallclover個(gè)人翻譯,因?yàn)橛⒄Z水平的原因可能會(huì)詞不達(dá)意,十分歡迎各位讀者指出其中的錯(cuò)誤,希望能對(duì)讀者有1%的用處,謝謝! 設(shè)計(jì)模式-裝飾器模式 裝飾器模式允許使用者將新功能添加到現(xiàn)有的對(duì)象而不需要改變它的數(shù)據(jù)結(jié)構(gòu)。這種類型的設(shè)計(jì)模式來源于...
摘要:裝飾對(duì)象包含一個(gè)真實(shí)對(duì)象的引用裝飾對(duì)象接受所有來自客戶端的請(qǐng)求。裝飾對(duì)象可以在轉(zhuǎn)發(fā)這些請(qǐng)求以前或以后增加一些附加功能。在面向?qū)ο蟮脑O(shè)計(jì)中,通常是通過繼承來實(shí)現(xiàn)對(duì)給定類的功能擴(kuò)展。 Decorator Pattern 裝飾者模式 綱要: 1. 一個(gè)初學(xué)者的疑惑 2. 裝飾者模式的特點(diǎn) 3. 簡單case掌握裝飾者模式 4. laravel中裝飾者模式的應(yīng)用 Con...
摘要:把和拼接在一起的場(chǎng)所是,所以需要造一個(gè)類,在其內(nèi)部實(shí)現(xiàn)對(duì)的操作中實(shí)現(xiàn)了把原有的進(jìn)過個(gè)的裝飾后得到的新的,新的還是的實(shí)現(xiàn),還是原來的物種。 說明:Laravel中Middleware的實(shí)現(xiàn)主要利用了Decorator Pattern的設(shè)計(jì),本文主要先學(xué)習(xí)下Decorator Pattern如何實(shí)現(xiàn),為后面學(xué)習(xí)Middleware的設(shè)計(jì)做個(gè)鋪墊。Decorator Pattern和Adap...
摘要:相關(guān)設(shè)計(jì)模式裝飾者模式和代理模式裝飾者模式關(guān)注再一個(gè)對(duì)象上動(dòng)態(tài)添加方法代理模式關(guān)注再對(duì)代理對(duì)象的控制訪問,可以對(duì)客戶隱藏被代理類的信息裝飾著模式和適配器模式都叫包裝模式關(guān)于新職責(zé)適配器也可以在轉(zhuǎn)換時(shí)增加新的職責(zé),但主要目的不在此。 0x01.定義與類型 定義:裝飾模式指的是在不必改變?cè)愇募褪褂美^承的情況下,動(dòng)態(tài)地?cái)U(kuò)展一個(gè)對(duì)象的功能。它是通過創(chuàng)建一個(gè)包裝對(duì)象,也就是裝飾來包裹真實(shí)的...
閱讀 3467·2023-04-25 23:25
閱讀 2110·2021-11-12 10:36
閱讀 2825·2019-08-30 12:47
閱讀 2049·2019-08-29 18:45
閱讀 447·2019-08-29 17:28
閱讀 1792·2019-08-29 17:15
閱讀 1717·2019-08-29 16:05
閱讀 1419·2019-08-29 14:17