結(jié)構(gòu)型設(shè)計模式 — 裝飾模式

真誠才是人生最高的品德膜毁。 — 喬叟

寫在前面

裝飾模式在不必改變類文件和使用繼承的情況下,可以動態(tài)的拓展一個對象的功能愤钾,是繼承的替代方案之一瘟滨。它通過創(chuàng)建包裝對象也就是裝飾者包裹真實的對象。

裝飾模式的定義:動態(tài)的給一個對象添加一些額外的功能能颁,就增加功能來說杂瘸,裝飾模式比生成子類更加靈活。

裝飾模式.jpg

抽象組件類(Component):可以是接口或者抽象類伙菊,被裝飾的最原始的對象败玉。
組件具體實現(xiàn)類(ConcreteComponent):Component的具體實現(xiàn)類,被裝飾的具體對象镜硕。
抽象裝飾類(Decorator):從外類來拓展Component類的功能运翼,但對于Component類來說無需知道Decorator的存在。在它的屬性中必然有一個私有變量指向Component抽象組件兴枯。
裝飾具體實現(xiàn)類(ConcreteDecorator):具體裝飾者血淌。

如何裝飾

下面通過一個例子來認識裝飾模式:

現(xiàn)在有一張畫紙,我畫了一頭奶牛财剖,但是因為我是色盲悠夯,所以就讓張三來幫忙給畫上色,上完色發(fā)現(xiàn)這副畫真的太好看了峰伙,倒不如裱起來掛到墻上欣賞疗疟,但是我不會该默,就讓李四來給這幅畫裝上畫框瞳氓。這里我是被裝飾者,張三和李四是裝飾者。

1.抽象組件類

我匣摘,張三和李四都要操作這幅畫店诗,我們都有操作的能力,所以要創(chuàng)建一個抽象類音榜,并聲明一個操作的方法庞瘸。

/**
 * 抽象組件類
 */
public abstract class Component {
    
    abstract void todo();
}
2.組件具體實現(xiàn)類

我只有畫的能力,上色和安裝畫框都是在我作畫的基礎(chǔ)上進行的赠叼,我要先作畫擦囊,因此我是被裝飾者。

/**
 * 組件具體實現(xiàn)類
 */
public class ConcreteComponent extends Component {
    @Override
    public void todo() {
        Log.d("ConcreteComponent", "我創(chuàng)作了一幅畫W彀臁K渤 !");
    }
}
3.抽象裝飾類

抽象裝飾類要持有對一個抽象組件的引用涧郊,方便調(diào)用被裝飾對象中的方法贯被,抽象裝飾類只是一個聲明。

/**
 * 抽象裝飾類
 */
public abstract class Decoratorextends Component {
    
    private Component mComponent;
    
    public Decorator(Component component) {
        mComponent = component;
    }
    
    @Override
    public void todo() {
        mComponent.todo();
    }
}
4.裝飾具體實現(xiàn)類

當(dāng)我做好了畫妆艘,張三和李四就要分別對畫進行上色和裝框了彤灶,張三和李四就是具體的裝飾類。

/**
 * 裝飾具體實現(xiàn)類
 */
public class ZhangSanDecorator extends Decorator {
    
    public ZhangSanDecorator(Component component) {
        super(component);
    }

    @Override
    public void todo() {
        super.todo();
        shangSe();
    }
    
    public void shangSe(){
        Log.d("張三", "給畫上色E;仙隆!");
    }
}

/**
 * 裝飾具體實現(xiàn)類
 */
public class LiSiDecorator extends Decorator {

    public LiSiDecorator(Component component) {
        super(component);
    }

    @Override
    public void todo() {
        super.todo();
        zhuangKuang();
    }

    public void zhuangKuang() {
        Log.d("李四", "給畫裝框V煳帧0巍!");
    }
}
5.開始裝飾

首先我要作畫逗物,張三和李四分別對我的畫進行裝飾搬卒,所以要將我作為參數(shù)傳給張三和李四,這樣他們就能在我作畫的基礎(chǔ)上對畫進行裝飾了翎卓。

/**
 * 客戶端
 */
public class Client {

   public Client() {
       // 創(chuàng)建我對象契邀,調(diào)用todo()方法作畫。
       ConcreteComponent me = new ConcreteComponent();
       me.todo();

       // 創(chuàng)建張三對象失暴,調(diào)用todo()方法給畫上色坯门。
       ZhangSanDecorator zhangSan = new ZhangSanDecorator(me);
       zhangSan.todo();

       // 創(chuàng)建李四對象,調(diào)用todo()方法給畫裝框
       LiSiDecorator liSi = new LiSiDecorator(me);
       liSi.todo();
   }
}

總結(jié)

裝飾模式的使用場景:

  • 在不影響其他對象的情況下逗扒,以動態(tài)古戴,透明的方式為單個對象添加職責(zé)。
  • 需要動態(tài)的為一個對象增加功能矩肩,這些功能可以動態(tài)的撤銷现恼。
  • 當(dāng)不能采用繼承的方式對系統(tǒng)進行擴充或者采用繼承的方式不利于系統(tǒng)擴展和維護時。

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

  • 通過組合而非繼承的方式,動態(tài)的擴展對象的功能叉袍,在運行時選擇不同的裝飾器始锚,從而實現(xiàn)不同的行為。
  • 有效避免了使用繼承的方式擴展對象功能而帶來的靈活性差喳逛,子類無限制擴張的問題瞧捌。
  • 具體組件類和具體裝飾類可以獨立變化,用戶可以根據(jù)需要增加新的具體組件類和具體裝飾類润文,在使用時再對其進行組合姐呐,原有代碼無需變化,符合“開發(fā)封閉原則”典蝌。

裝飾模式的缺點:

  • 因為所有對象均繼承于Component皮钠,所以如果Component內(nèi)部結(jié)構(gòu)發(fā)生改變,則不可避免的影響所有子類赠法,就是會影響裝飾者和被裝飾者麦轰。
  • 比繼承更加靈活機動的特性,也同時意味者裝飾模式比繼承更加容易出錯砖织,排錯也很困難款侵。對于多次裝飾的對象,調(diào)試時尋找錯誤可能需要逐級排查侧纯,較為繁瑣新锈。所以只在必要的時候使用裝飾模式。
  • 裝飾層數(shù)不能過多眶熬,否則會影響效率妹笆。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市娜氏,隨后出現(xiàn)的幾起案子芳来,更是在濱河造成了極大的恐慌腥例,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蜜葱,居然都是意外死亡汁胆,警方通過查閱死者的電腦和手機答毫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門摹量,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人盔憨,你說我怎么就攤上這事徙菠。” “怎么了郁岩?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵婿奔,是天一觀的道長芙盘。 經(jīng)常有香客問我,道長脸秽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任蝴乔,我火速辦了婚禮记餐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘薇正。我一直安慰自己片酝,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布挖腰。 她就那樣靜靜地躺著雕沿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪猴仑。 梳的紋絲不亂的頭發(fā)上审轮,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音辽俗,去河邊找鬼疾渣。 笑死,一個胖子當(dāng)著我的面吹牛崖飘,可吹牛的內(nèi)容都是我干的榴捡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼朱浴,長吁一口氣:“原來是場噩夢啊……” “哼吊圾!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起翰蠢,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤项乒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后梁沧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體板丽,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年趁尼,在試婚紗的時候發(fā)現(xiàn)自己被綠了埃碱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡酥泞,死狀恐怖砚殿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芝囤,我是刑警寧澤似炎,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布辛萍,位于F島的核電站,受9級特大地震影響羡藐,放射性物質(zhì)發(fā)生泄漏贩毕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一仆嗦、第九天 我趴在偏房一處隱蔽的房頂上張望辉阶。 院中可真熱鬧,春花似錦瘩扼、人聲如沸谆甜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽规辱。三九已至,卻和暖如春栽燕,著一層夾襖步出監(jiān)牢的瞬間罕袋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工碍岔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留炫贤,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓付秕,卻偏偏與公主長得像兰珍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子询吴,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

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