知識整理No6.之#裝飾者Decorator

裝飾者Decorator

背景

問題

  • 你如何組織你的代碼使其可以容易的添加基本的或者一些很少用到的 特性,而不是直接不額外的代碼寫在你的類的內(nèi)部?

解決方案

  • 裝飾器模式: 動態(tài)地給一個(gè)對象添加一些額外的職責(zé)或者行為。就增加功能來說, Decorator模式相比生成子類更為靈活。
  • 裝飾器模式提供了改變子類的靈活方案。裝飾器模式在不必改變原類文件和使用繼承的情況下,動態(tài)的擴(kuò)展一個(gè)對象的功能。它是通過創(chuàng)建一個(gè)包裝對象,也就是裝飾來包裹真實(shí)的對象。
  • 當(dāng)用于一組子類時(shí),裝飾器模式更加有用。如果你擁有一族子類(從一個(gè)父類派生而來),你需要在與子類獨(dú)立使用情況下添加額外的特性,你可以使用裝飾器模式,以避免代碼重復(fù)和具體子類數(shù)量的增加。

剖析

意圖

  • 將額外的責(zé)任自動附加到一個(gè)對象上。裝飾模式提供了靈活的子類來擴(kuò)展功能
  • client-specified 通過封裝裝飾了一個(gè)核心對象
  • 包裝禮物,放進(jìn)盒子里,包裝盒子

定義

  • 動態(tài)地改一個(gè)對象添加一些額外的職責(zé)。就增加功能來說,裝飾模式比生成子類更為靈活

本質(zhì)

  • 動態(tài)組合

模式講解

  • 動態(tài)的實(shí)現(xiàn)為對象添加功能
  • 思考起點(diǎn): 對象組合
  • 裝飾器:給被裝飾對象增加功能,還可以根據(jù)需要選擇是否調(diào)用裝飾對象的功能
  • 裝飾器一定要和組件類一致的接口,保證他們是同一個(gè)類型,并具有同一個(gè)外觀
  • 退化形式:沒有必要設(shè)計(jì)抽象類了

特點(diǎn)

(1) 裝飾對象和真實(shí)對象有相同的接口。這樣客戶端對象就可以以和真實(shí)對象相同的方式和裝飾對象交互。
  (2) 裝飾對象包含一個(gè)真實(shí)對象的索引(reference)
  (3) 裝飾對象接受所有的來自客戶端的請求。它把這些請求轉(zhuǎn)發(fā)給真實(shí)的對象。

(4) 裝飾對象可以在轉(zhuǎn)發(fā)這些請求以前或以后增加一些附加功能。這樣就確保了在運(yùn)行時(shí),不用修改給定對象的結(jié)構(gòu)就可以在外部增加附加的功能。在面向?qū)ο蟮脑O(shè)計(jì)中,通常是通過繼承來實(shí)現(xiàn)對給定類的功能擴(kuò)展。

UML

Decorator-UML.png

模式的組成

抽象組件角色(Component):定義一個(gè)對象接口,以規(guī)范準(zhǔn)備接受附加責(zé)任的對象,

即可以給這些對象動態(tài)地添加職責(zé)。

具體組件角色(ConcreteComponent) :被裝飾者,定義一個(gè)將要被裝飾增加功能的類。

可以給這個(gè)類的對象添加一些職責(zé)

抽象裝飾器(Decorator):維持一個(gè)指向構(gòu)件Component對象的實(shí)例,

并定義一個(gè)與抽象組件角色Component接口一致的接口

具體裝飾器角色(ConcreteDecorator):向組件添加職責(zé)。

Example

Decorator-example.png

場景

  • 何時(shí)使用

1.想在不影響其它對象的情況下,以動態(tài),透明的方式給單個(gè)對象添加職責(zé)。
2.想要擴(kuò)展一個(gè)類的行為,卻做不到。類定義可能被隱藏,無法進(jìn)行子類化,或者對類的每個(gè)行為的擴(kuò)展,為支持每種功能組合,將產(chǎn)生大量的子類。

  • 使用場景

1.需要擴(kuò)展一個(gè)類的功能,或給一個(gè)類增加附加功能
2.需要動態(tài)的給一個(gè)對象添加功能,這些功能可以再動態(tài)的側(cè)撤銷
3.為一批兄弟類進(jìn)行改裝或加裝功能
對繼承的有力補(bǔ)充

優(yōu)缺點(diǎn)

  1. 比靜態(tài)繼承更靈活: 與對象的靜態(tài)繼承(多重繼承)相比, Decorator模式提供了更加靈活的向?qū)ο筇砑勇氊?zé)的方式。可以用添加和分離的方法,用裝飾在運(yùn)行時(shí)刻增加和刪除職責(zé)。相比之下,繼承機(jī)制要求為每個(gè)添加的職責(zé)創(chuàng)建一個(gè)新的子類。這會產(chǎn)生許多新的類,并且會增加系統(tǒng)的復(fù)雜度。此外,為一個(gè)特定的Component類提供多個(gè)不同的 Decorator類,這就使得你可以對一些職責(zé)進(jìn)行混合和匹配。使用Decorator模式可以很容易地重復(fù)添加一個(gè)特性。
  2. 避免在層次結(jié)構(gòu)高層的類有太多的特征 Decorator模式提供了一種“即用即付”的方法來添加職責(zé)。它并不試圖在一個(gè)復(fù)雜的可定制的類中支持所有可預(yù)見的特征,相反,你可以定義一個(gè)簡單的類,并且用 Decorator類給它逐漸地添加功能。可以從簡單的部件組合出復(fù)雜的功能。這樣,應(yīng)用程序不必為不需要的特征付出代價(jià)。同時(shí)更易于不依賴于 Decorator所擴(kuò)展(甚至是不可預(yù)知的擴(kuò)展)的類而獨(dú)立地定義新類型的 Decorator。擴(kuò)展一個(gè)復(fù)雜類的時(shí)候,很可能會暴露與添加的職責(zé)無關(guān)的細(xì)節(jié)。
  3. Decorator與它的Component不一樣 Decorator是一個(gè)透明的包裝。如果我們從對象標(biāo)識的觀點(diǎn)出發(fā),一個(gè)被裝飾了的組件與這個(gè)組件是有差別的,因此,使用裝飾不應(yīng)該依賴對象標(biāo)識。
  4. 有許多小對象 采用Decorator模式進(jìn)行系統(tǒng)設(shè)計(jì)往往會產(chǎn)生許多看上去類似的小對象,這些對象僅僅在他們相互連接的方式上有所不同,而不是它們的類或是它們的屬性值有所不同。盡管對于那些了解這些系統(tǒng)的人來說,很容易對它們進(jìn)行定制,但是很難學(xué)習(xí)這些系統(tǒng),排錯也很困難。

優(yōu)點(diǎn)

  • 比繼承更靈活
  • 更容易復(fù)用功能
  • 簡化高層定義

缺點(diǎn)

  • 產(chǎn)生很多細(xì)粒度對象
  • 相關(guān)模式
  • 策略模式

相關(guān)模式

1)Adapter 模式:Decorator模式不同于Adapter模式,因?yàn)檠b飾僅改變對象的職責(zé)而

不改變它的接口;而適配器將給對象一個(gè)全新的接口。

2)Composite模式:可以將裝飾視為一個(gè)退化的、僅有一個(gè)組件的組

合。然而,裝飾僅給對象添加一些額外的職責(zé)—它的目的不在于對象聚集。

3)Strategy模式:用一個(gè)裝飾你可以改變對象的外表;而Strategy模

式使得你可以改變對象的內(nèi)核。這是改變對象的兩種途徑。

經(jīng)驗(yàn)法則

  • 適配器提供不同的接口給他的子對象。代理提供相同的接口,裝飾模式增強(qiáng)了接口
  • 適配器改變了對象的接口,裝飾器加強(qiáng)了對象的責(zé)任。裝飾器模式對客戶端更加透明。因此,裝飾支持遞歸組合,并不是純粹的適配器
  • 組合模式和裝飾器模式有相同結(jié)構(gòu)的語法,反映了遞歸組合管理開放對象樹
  • 修飾符可以被視為一種只有一個(gè)退化符合組件。裝飾模式增加了額外的模式--他不是面向?qū)ο缶酆?/li>
  • 裝飾模式設(shè)計(jì)目的為了讓你給對象增加責(zé)任而不是子類。組合類的目的不是裝飾而是表示。他們的目的不同,但是互補(bǔ)。
  • 組合使用責(zé)任鏈模式通過父類訪問全局性。在組合模式部分組成中也使用裝飾模式覆蓋這些屬性。
  • 裝飾模式和代理模式有不同的目的但是相同的結(jié)構(gòu)。提供了另一個(gè)對象間接層。,實(shí)現(xiàn)了保留了一個(gè)引用到前向請求的對象。
  • 裝飾模式改變了對象的外部。策略模式改變了內(nèi)部。

總結(jié)

  • 1)使用裝飾器設(shè)計(jì)模式設(shè)計(jì)類的目標(biāo)是: 不必重寫任何已有的功能性代碼,而是對某個(gè)基于對象應(yīng)用增量變化。

    1. 裝飾器設(shè)計(jì)模式采用這樣的構(gòu)建方式: 在主代碼流中應(yīng)該能夠直接插入一個(gè)或多個(gè)更改或“裝飾”目標(biāo)對象的裝飾器,同時(shí)不影響其他代碼流。
    1. Decorator模式采用對象組合而非繼承的手法,實(shí)現(xiàn)了在運(yùn)行時(shí)動態(tài)的擴(kuò)展對象功能的能力,而且可以根據(jù)需要擴(kuò)展多個(gè)功能,避免了單獨(dú)使用繼承帶來的“靈活性差”和“多子類衍生問題”。
      同時(shí)它很好地符合面向?qū)ο笤O(shè)計(jì)原則中“優(yōu)先使用對象組合而非繼承”和“開放-封閉”原則。
      也許裝飾器模式最重要的一個(gè)方面是它的超過繼承的能力。“問題”部分展現(xiàn)了一個(gè)使用繼承的子類爆炸。
      基于裝飾器模式的解決方案,UML類圖展現(xiàn)了這個(gè)簡潔靈活的解決方案。

從外部變更

每個(gè)節(jié)點(diǎn)不知道裝飾(外表的變更)

策略(內(nèi)容的變更)

從內(nèi)部變更

每個(gè)節(jié)點(diǎn)知道一組預(yù)定義的變更方式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,362評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,577評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,486評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,852評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,600評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,944評論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,944評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,108評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,652評論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,385評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,616評論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,111評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,798評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,205評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,537評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,334評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,570評論 2 379

推薦閱讀更多精彩內(nèi)容

  • 1 場景問題# 1.1 復(fù)雜的獎金計(jì)算## 考慮這樣一個(gè)實(shí)際應(yīng)用:就是如何實(shí)現(xiàn)靈活的獎金計(jì)算。 獎金計(jì)算是相對復(fù)雜...
    七寸知架構(gòu)閱讀 4,045評論 4 67
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 3,961評論 1 15
  • 設(shè)計(jì)模式基本原則 開放-封閉原則(OCP),是說軟件實(shí)體(類、模塊、函數(shù)等等)應(yīng)該可以拓展,但是不可修改。開-閉原...
    西山薄涼閱讀 3,845評論 3 14
  • 設(shè)計(jì)原則: 少用繼承,多用組合 類應(yīng)該對擴(kuò)展開放,對修改關(guān)閉 目錄 本文的結(jié)構(gòu)如下: 什么是裝飾者模式 為什么要用...
    w1992wishes閱讀 1,202評論 0 7
  • 1 孤獨(dú)的時(shí)候,不要找你喜歡的女生聊天。這是一種侵犯。這種時(shí)候,你大腦里沒有什么內(nèi)容,你空有聊天的欲望卻沒有聊天的...
    阿做閱讀 428評論 0 1