裝飾者模式

在《JAVA與模式》一書開頭是這樣描述裝飾(Decorator)模式的:

裝飾模式又名包裝模式墓卦。裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關(guān)系的一個替代方案珊膜。

1. 模式動機

一般有兩種方式可以實現(xiàn)給一個類或?qū)ο笤黾有袨椋?/p>

  • 繼承機制晌坤,適用繼承機制是給現(xiàn)有類添加功能的一種有效途徑芋膘,通過繼承一個現(xiàn)有類可以使得子類在擁有自身方法的同時還擁有父類的方法。但是這種方法是靜態(tài)的衙四,用戶不能控制增加行為的方式和時機铃肯。
  • 關(guān)聯(lián)機制,即將一個類的對象嵌入另一個對象中传蹈,由另一個對象來決定是否調(diào)用嵌入對象的行為以便擴展自己的行為押逼,我們稱這個嵌入的對象為裝飾器
    裝飾模式以對客戶透明的方式動態(tài)地給一個對象附加上更多的責任,換言之惦界,客戶端并不會覺得對象在裝飾前和裝飾后由什么不同挑格。裝飾模式可以在不需要創(chuàng)建更多子類的情況下,將對象的功能加以擴展沾歪。這就是裝飾模式的模式動機漂彤。

2. 模式定義

裝飾模式:動態(tài)地給一個對象增加一些額外的職責,就增加對象功能來說灾搏,裝飾模式比生成子類實現(xiàn)更為靈活挫望。其別名也可以成為包裝器,與適配器模式的別名相同确镊,但它們適用于不同的場合士骤。根據(jù)翻譯的不同,裝飾模式也有人稱之為“油漆工模式”蕾域,它是一種對象結(jié)構(gòu)性模式拷肌。

3. 模式結(jié)構(gòu)

裝飾模式包含如下角色:

  • Component:抽象構(gòu)建
  • ConcreateComponent:具體構(gòu)建
  • Decorator:抽象裝飾類
  • ConcreateDecorator:具體裝飾類


    image

4. 時序圖

image

5. 代碼分析

/**
 * 抽象構(gòu)建
 */
public interface Component {
    void operation();
}
/**
 * 具體構(gòu)建
 */
public class ConcreteComponent implements Component {
    private String name;
    ConcreteComponent(String name){
        this.name = name;
    }

    @Override
    public void operation() {
        System.out.println("裝扮的" + name);
    }
}
/**
 * 抽象裝飾類
 */
public abstract class Decorator implements Component {

     public Component component;

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        if(component != null)
            component.operation();
    }
}
/**
 * 具體裝飾類
 */
public class ConcreteDecoratorA extends Decorator {

    @Override
    public void operation() {
        super.operation();
        System.out.println("穿大衣");
    }
}
/**
 * 具體裝飾類
 */
public class ConcreteDecoratorB extends Decorator {

    @Override
    public void operation() {
        super.operation();
        System.out.println("穿跨褲??");
    }
}
public class MainClass {
    public static void main(String[] args) {
        ConcreteComponent xiaocai = new ConcreteComponent("小菜");
        ConcreteDecoratorA dayi = new ConcreteDecoratorA();
        ConcreteDecoratorB kuzi = new ConcreteDecoratorB();
        dayi.setComponent(xiaocai);
        kuzi.setComponent(dayi);
        kuzi.operation();
    }
}

運行結(jié)果


image.png

6. 模式分析

  • 與繼承關(guān)系相比,關(guān)聯(lián)關(guān)系的主要優(yōu)勢在于不會破壞類的封裝行旨巷,而且繼承是一種耦合度較大的靜態(tài)關(guān)系巨缘,無法在程序運行時動態(tài)擴展。在軟件開發(fā)階段采呐,關(guān)聯(lián)關(guān)系雖然不會比繼承關(guān)系減少編碼量若锁,但是到了軟件維護階段,由于關(guān)聯(lián)關(guān)系使系統(tǒng)具有較好的松耦合性斧吐,因此使得系統(tǒng)更加容易維護又固。當然關(guān)聯(lián)關(guān)系的缺點是比繼承關(guān)系要創(chuàng)建更多的對象仲器。
  • 使用裝飾者模式實現(xiàn)擴展比繼承更加靈活,它以對客戶透明的方式動態(tài)的給一個對象附加更多的責任仰冠。裝飾模式可以在不需要創(chuàng)造更多子類的情況下乏冀,將對象的功能加一擴展。

7. 優(yōu)點

裝飾模式的優(yōu)點:

  • 裝飾模式與繼承關(guān)系的目的都是要擴展對象的功能洋只,但是裝飾模式可以提供比繼承更多的靈活性辆沦。
  • 可以通過一種動態(tài)的方式來擴展一個對象的功能,通過配置文件可以在運行時選擇不同的裝飾器识虚,從而實現(xiàn)不同的行為肢扯。
  • 通過使用不同的具體裝飾類以及這些裝飾類的排列組合,可以創(chuàng)造出很多不同行為的組合担锤∥党浚可以使用多個具體裝飾類來裝飾同一對象,得到功能更為強大的對象妻献。
  • 具體構(gòu)建類與具體裝飾類可以獨立變化蛛株,用戶可以根據(jù)需要增加新的具體構(gòu)建類和具體裝飾類,在使用時在對其進行組合育拨,原有代碼無須改變谨履,符合“開閉原則”。

8. 缺點

裝飾模式的缺點:

  • 使用裝飾模式進行系統(tǒng)設(shè)計時將產(chǎn)生很多小對象熬丧,這些對象的區(qū)別在于它們之間相互連接的方式有所不同笋粟,而不是它們的類或者屬性值有所不同,同時還將產(chǎn)生很多具體裝飾類析蝴。這些裝飾類和小對象的產(chǎn)生將增加系統(tǒng)的復(fù)雜性害捕,加大學(xué)習(xí)與理解的難度。
  • 這種比繼承更加靈活機動的特性闷畸,也同時意味著裝飾模式比繼承更加易于出錯尝盼,排錯也很困難,對于多次裝飾的對象佑菩,調(diào)試時尋找錯誤可能需要逐級排查盾沫,較為繁瑣。

9. 適用環(huán)境

在以下情況下可以使用裝飾模式:

  • 在不影響其他對象的情況下殿漠,以動態(tài)赴精、透明的方式給單個對象添加職責
  • 需要動態(tài)的給一個對象增加功能,這些功能也可以動態(tài)的被撤銷绞幌。
  • 當不能采用繼承的方式對系統(tǒng)進行擴充或者采用繼承不利于系統(tǒng)擴展和維護時蕾哟。不能采用繼承的情況主要有兩類:第一類是系統(tǒng)中存在大量獨立的擴展,為支持每一種組合將產(chǎn)生大量的子類,使得子類數(shù)目呈爆炸增長谭确;第二類是因為類定義不能繼承(如final類)帘营。

10. 模式應(yīng)用

裝飾模式在Java語言中最著名的應(yīng)用莫過于Java I/O標準庫的設(shè)計了。

11. 模式擴展

裝飾模式的簡化-需要注意的問題:

  • 一個裝飾類的接口必須與被裝飾類的接口保持相同琼富,對于客戶端來說無論是裝飾之前的對象還是裝飾之后的對象都可以一致對待仪吧。
  • 盡量保持具體構(gòu)件類Component作為一個“輕”類庄新,也就是說不要把太多的邏輯和狀態(tài)放在具體構(gòu)件類中鞠眉,可以通過裝飾類對其進行擴展。 - 如果只有一個具體構(gòu)件類而沒有抽象構(gòu)件類择诈,那么抽象裝飾類可以作為具體構(gòu)件類的直接子類械蹋。

12. 總結(jié)

  • 裝飾模式用于動態(tài)地給一個對象增加一些額外的職責,就增加對象功 能來說羞芍,裝飾模式比生成子類實現(xiàn)更為靈活哗戈。它是一種對象結(jié)構(gòu)型模 式。
  • 裝飾模式包含四個角色:抽象構(gòu)件定義了對象的接口荷科,可以給這些對 象動態(tài)增加職責(方法)唯咬;具體構(gòu)件定義了具體的構(gòu)件對象,實現(xiàn)了 在抽象構(gòu)件中聲明的方法畏浆,裝飾器可以給它增加額外的職責(方法)胆胰; 抽象裝飾類是抽象構(gòu)件類的子類,用于給具體構(gòu)件增加職責刻获,但是具 體職責在其子類中實現(xiàn)蜀涨;具體裝飾類是抽象裝飾類的子類,負責向構(gòu) 件添加新的職責蝎毡。
  • 使用裝飾模式來實現(xiàn)擴展比繼承更加靈活厚柳,它以對客戶透明的方式動 態(tài)地給一個對象附加更多的責任。裝飾模式可以在不需要創(chuàng)造更多子 類的情況下沐兵,將對象的功能加以擴展别垮。
  • 裝飾模式的主要優(yōu)點在于可以提供比繼承更多的靈活性,可以通過一種動態(tài)的 方式來擴展一個對象的功能扎谎,并通過使用不同的具體裝飾類以及這些裝飾類的 排列組合碳想,可以創(chuàng)造出很多不同行為的組合,而且具體構(gòu)件類與具體裝飾類可 以獨立變化簿透,用戶可以根據(jù)需要增加新的具體構(gòu)件類和具體裝飾類移袍;其主要缺 點在于使用裝飾模式進行系統(tǒng)設(shè)計時將產(chǎn)生很多小對象,而且裝飾模式比繼承 更加易于出錯老充,排錯也很困難葡盗,對于多次裝飾的對象,調(diào)試時尋找錯誤可能需 要逐級排查,較為煩瑣觅够。
  • 裝飾模式適用情況包括:在不影響其他對象的情況下胶背,以動態(tài)、透明的方式給 單個對象添加職責喘先;需要動態(tài)地給一個對象增加功能钳吟,這些功能也可以動態(tài)地 被撤銷;當不能采用繼承的方式對系統(tǒng)進行擴充或者采用繼承不利于系統(tǒng)擴展 和維護時窘拯。
  • 裝飾模式可分為透明裝飾模式和半透明裝飾模式:在透明裝飾模式中红且,要求客 戶端完全針對抽象編程,裝飾模式的透明性要求客戶端程序不應(yīng)該聲明具體構(gòu) 件類型和具體裝飾類型涤姊,而應(yīng)該全部聲明為抽象構(gòu)件類型暇番;半透明裝飾模式允 許用戶在客戶端聲明具體裝飾者類型的對象,調(diào)用在具體裝飾者中新增的方法思喊。

參照圖悅設(shè)計模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壁酬,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子恨课,更是在濱河造成了極大的恐慌舆乔,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剂公,死亡現(xiàn)場離奇詭異希俩,居然都是意外死亡,警方通過查閱死者的電腦和手機诬留,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門斜纪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人文兑,你說我怎么就攤上這事盒刚。” “怎么了绿贞?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵因块,是天一觀的道長。 經(jīng)常有香客問我籍铁,道長涡上,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任拒名,我火速辦了婚禮吩愧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘增显。我一直安慰自己雁佳,他們只是感情好,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著糖权,像睡著了一般堵腹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上星澳,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天疚顷,我揣著相機與錄音,去河邊找鬼禁偎。 笑死腿堤,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的届垫。 我是一名探鬼主播释液,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼装处!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起浸船,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤妄迁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后李命,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體登淘,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年封字,在試婚紗的時候發(fā)現(xiàn)自己被綠了黔州。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡阔籽,死狀恐怖流妻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情笆制,我是刑警寧澤绅这,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站在辆,受9級特大地震影響证薇,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜匆篓,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一浑度、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸦概,春花似錦箩张、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽横漏。三九已至,卻和暖如春熟掂,著一層夾襖步出監(jiān)牢的瞬間缎浇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工赴肚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留素跺,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓誉券,卻偏偏與公主長得像指厌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踊跟,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

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

  • 設(shè)計模式概述 在學(xué)習(xí)面向?qū)ο笃叽笤O(shè)計原則時需要注意以下幾點:a) 高內(nèi)聚踩验、低耦合和單一職能的“沖突”實際上,這兩者...
    彥幀閱讀 3,734評論 0 14
  • 設(shè)計原則: 少用繼承商玫,多用組合 類應(yīng)該對擴展開放箕憾,對修改關(guān)閉 目錄 本文的結(jié)構(gòu)如下: 什么是裝飾者模式 為什么要用...
    w1992wishes閱讀 1,148評論 0 7
  • 本篇文章介紹一種設(shè)計模式——裝飾者模式。裝飾者模式在Java中的典型應(yīng)用就是IO流拳昌,在本篇文章中將有詳細介紹袭异。本篇...
    Ruheng閱讀 22,165評論 13 56
  • 每當我們買了新房子之后,相信絕大部分人都會進行裝修炬藤,給房子增加一些其他新的物品御铃。不過,無論如何裝修沈矿,這個房子還是這...
    帥地閱讀 260評論 0 3
  • 裝飾模式是一種用于替代繼承的技術(shù)上真,它通過一種無須定義子類的方式來給對象動態(tài)增加職責,使用對象之間的關(guān)聯(lián)關(guān)系取代類之...
    stoneyang94閱讀 356評論 0 0