java中裝飾模式

本文參考:
http://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/decorator.html

http://www.cnblogs.com/jingmoxukong/p/4226237.html

一、模式動機

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

  • 繼承機制站粟,使用繼承機制是給現(xiàn)有類添加功能的一種有效途徑,通過繼承一個現(xiàn)有類可以使得子類在擁有自身方法的同時還擁有父類的方法顽馋。但是這種方法是靜態(tài)的皱碘,用戶不能控制增加行為的方式和時機。
  • 關聯(lián)機制均唉,即將一個類的對象嵌入另一個對象中是晨,由另一個對象來決定是否調(diào)用嵌入對象的行為以便擴展自己的行為,我們稱這個嵌入的對象為裝飾器(Decorator)

裝飾模式以對客戶透明的方式動態(tài)地給一個對象附加上更多的責任舔箭,換言之罩缴,客戶端并不會覺得對象在裝飾前和裝飾后有什么不同。裝飾模式可以在不需要創(chuàng)造更多子類的情況下层扶,將對象的功能加以擴展箫章。這就是裝飾模式的模式動機。

二镜会、模式定義

裝飾模式(Decorator Pattern) :動態(tài)地給一個對象增加一些額外的職責(Responsibility)檬寂,就增加對象功能來說,裝飾模式比生成子類實現(xiàn)更為靈活戳表。其別名也可以稱為包裝器(Wrapper)桶至,與適配器模式的別名相同,但它們適用于不同的場合匾旭。根據(jù)翻譯的不同镣屹,裝飾模式也有人稱之為“油漆工模式”,它是一種對象結(jié)構(gòu)型模式价涝。

三女蜈、模式結(jié)構(gòu)

裝飾模式包含如下角色:

  • Component: 抽象構(gòu)件
  • ConcreteComponent: 具體構(gòu)件
  • Decorator: 抽象裝飾類
  • ConcreteDecorator: 具體裝飾類
image

四、代碼分析

Component

public interface Component {
    public void operation();
}

ConcreteComponent

public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("init operation...");
    }
}

Decorator

public class Decorator implements Component {
    // 持有一個 Component 對象色瘩,和 Component 形成聚合關系
    protected Component component;

    // 傳入要進一步修飾的對象
    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}

ConcreateDecorator

public class ConcreteDecoratorA extends Decorator {
    private String addedState = "new feature 1";

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

    public void operation() {
        super.operation();
        System.out.println("add feature 1: " + addedState);
    }
}

public class ConcreteDecoratorB extends Decorator {
    public ConcreteDecoratorB(Component component) {
        super(component);
    }

    public void operation() {
        super.operation();
        AddedBehavior();
    }

    public void AddedBehavior() {
        System.out.println("add behavior");
    }
}

Client

public class DecoratorPattern {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        component.operation();

        System.out.println("======================================");
        Decorator decoratorA = new ConcreteDecoratorA(component);
        decoratorA.operation();

        System.out.println("======================================");
        Decorator decoratorB = new ConcreteDecoratorB(decoratorA);
        decoratorB.operation();
    }
}

輸出內(nèi)容:

init operation...
======================================
init operation...
add feature 1: new feature 1
======================================
init operation...
add feature 1: new feature 1
add behavior

五鞭光、模式分析

  • 與繼承關系相比,關聯(lián)關系的主要優(yōu)勢在于不會破壞類的封裝性泞遗,而且繼承是一種耦合度較大的靜態(tài)關系惰许,無法在程序運行時動態(tài)擴展。在軟件開發(fā)階段史辙,關聯(lián)關系雖然不會比繼承關系減少編碼量汹买,但是到了軟件維護階段佩伤,由于關聯(lián)關系使系統(tǒng)具有較好的松耦合性,因此使得系統(tǒng)更加容易維護晦毙。當然生巡,關聯(lián)關系的缺點是比繼承關系要創(chuàng)建更多的對象。
  • 使用裝飾模式來實現(xiàn)擴展比繼承更加靈活见妒,它以對客戶透明的方式動態(tài)地給一個對象附加更多的責任孤荣。裝飾模式可以在不需要創(chuàng)造更多子類的情況下,將對象的功能加以擴展须揣。

六盐股、優(yōu)點

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

  • 裝飾模式與繼承關系的目的都是要擴展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性耻卡。
  • 可以通過一種動態(tài)的方式來擴展一個對象的功能疯汁,通過配置文件可以在運行時選擇不同的裝飾器,從而實現(xiàn)不同的行為卵酪。
  • 通過使用不同的具體裝飾類以及這些裝飾類的排列組合幌蚊,可以創(chuàng)造出很多不同行為的組合±?ǎ可以使用多個具體裝飾類來裝飾同一對象溢豆,得到功能更為強大的對象。
  • 具體構(gòu)件類與具體裝飾類可以獨立變化瘸羡,用戶可以根據(jù)需要增加新的具體構(gòu)件類和具體裝飾類漩仙,在使用時再對其進行組合,原有代碼無須改變最铁,符合“開閉原則”

七讯赏、缺點

裝飾模式的缺點:

  • 使用裝飾模式進行系統(tǒng)設計時將產(chǎn)生很多小對象,這些對象的區(qū)別在于它們之間相互連接的方式有所不同冷尉,而不是它們的類或者屬性值有所不同漱挎,同時還將產(chǎn)生很多具體裝飾類。這些裝飾類和小對象的產(chǎn)生將增加系統(tǒng)的復雜度雀哨,加大學習與理解的難度磕谅。
  • 這種比繼承更加靈活機動的特性,也同時意味著裝飾模式比繼承更加易于出錯雾棺,排錯也很困難膊夹,對于多次裝飾的對象,調(diào)試時尋找錯誤可能需要逐級排查捌浩,較為煩瑣放刨。

八、適用環(huán)境

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

  • 在不影響其他對象的情況下尸饺,以動態(tài)进统、透明的方式給單個對象添加職責助币。
  • 需要動態(tài)地給一個對象增加功能,這些功能也可以動態(tài)地被撤銷螟碎。
  • 當不能采用繼承的方式對系統(tǒng)進行擴充或者采用繼承不利于系統(tǒng)擴展和維護時眉菱。不能采用繼承的情況主要有兩類:第一類是系統(tǒng)中存在大量獨立的擴展,為支持每一種組合將產(chǎn)生大量的子類掉分,使得子類數(shù)目呈爆炸性增長俭缓;第二類是因為類定義不能繼承(如final類).

九、模式擴展

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

  • 一個裝飾類的接口必須與被裝飾類的接口保持相同酥郭,對于客戶端來說無論是裝飾之前的對象還是裝飾之后的對象都可以一致對待华坦。
  • 盡量保持具體構(gòu)件類Component作為一個“輕”類,也就是說不要把太多的邏輯和狀態(tài)放在具體構(gòu)件類中褥民,可以通過裝飾類對其進行擴展季春。
  • 如果只有一個具體構(gòu)件類而沒有抽象構(gòu)件類洗搂,那么抽象裝飾類可以作為具體構(gòu)件類的直接子類消返。

十、總結(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)設計時將產(chǎn)生很多小對象,而且裝飾模式比繼承 更加易于出錯挥等,排錯也很困難友绝,對于多次裝飾的對象,調(diào)試時尋找錯誤可能需 要逐級排查肝劲,較為煩瑣迁客。
  • 裝飾模式適用情況包括:在不影響其他對象的情況下,以動態(tài)辞槐、透明的方式給 單個對象添加職責掷漱;需要動態(tài)地給一個對象增加功能,這些功能也可以動態(tài)地 被撤銷榄檬;當不能采用繼承的方式對系統(tǒng)進行擴充或者采用繼承不利于系統(tǒng)擴展 和維護時卜范。
  • 裝飾模式可分為透明裝飾模式和半透明裝飾模式:在透明裝飾模式中,要求客 戶端完全針對抽象編程鹿榜,裝飾模式的透明性要求客戶端程序不應該聲明具體構(gòu) 件類型和具體裝飾類型海雪,而應該全部聲明為抽象構(gòu)件類型;半透明裝飾模式允 許用戶在客戶端聲明具體裝飾者類型的對象舱殿,調(diào)用在具體裝飾者中新增的方法奥裸。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市沪袭,隨后出現(xiàn)的幾起案子湾宙,更是在濱河造成了極大的恐慌,老刑警劉巖冈绊,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侠鳄,死亡現(xiàn)場離奇詭異,居然都是意外死亡死宣,警方通過查閱死者的電腦和手機伟恶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來十电,“玉大人知押,你說我怎么就攤上這事【槁睿” “怎么了台盯?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長畏线。 經(jīng)常有香客問我静盅,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任蒿叠,我火速辦了婚禮明垢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘市咽。我一直安慰自己痊银,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布施绎。 她就那樣靜靜地躺著溯革,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谷醉。 梳的紋絲不亂的頭發(fā)上致稀,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音俱尼,去河邊找鬼抖单。 笑死,一個胖子當著我的面吹牛遇八,可吹牛的內(nèi)容都是我干的矛绘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼押蚤,長吁一口氣:“原來是場噩夢啊……” “哼蔑歌!你這毒婦竟也來了羹应?” 一聲冷哼從身側(cè)響起揽碘,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎园匹,沒想到半個月后雳刺,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡裸违,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年掖桦,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片供汛。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡枪汪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怔昨,到底是詐尸還是另有隱情雀久,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布趁舀,位于F島的核電站赖捌,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏矮烹。R本人自食惡果不足惜越庇,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一罩锐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卤唉,春花似錦涩惑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碰纬,卻和暖如春萍聊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悦析。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工寿桨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人强戴。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓亭螟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親骑歹。 傳聞我的和親對象是個殘疾皇子预烙,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

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

  • 設計模式匯總 一、基礎知識 1. 設計模式概述 定義:設計模式(Design Pattern)是一套被反復使用道媚、多...
    MinoyJet閱讀 3,906評論 1 15
  • 1. Java基礎部分 基礎部分的順序:基本語法扁掸,類相關的語法,內(nèi)部類的語法最域,繼承相關的語法谴分,異常的語法,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • 設計原則: 少用繼承镀脂,多用組合 類應該對擴展開放牺蹄,對修改關閉 目錄 本文的結(jié)構(gòu)如下: 什么是裝飾者模式 為什么要用...
    w1992wishes閱讀 1,148評論 0 7
  • (轉(zhuǎn)載)原文地址 在閻宏博士的《JAVA與模式》一書中開頭是這樣描述裝飾(Decorator)模式的: 裝飾模式又...
    zjk_00閱讀 629評論 0 2
  • 現(xiàn)在是2016年10月24日早晨5點32分,我的閱讀進行了26分鐘薄翅,讀完了《拖延》的第6章沙兰。 客觀...
    不著子閱讀 377評論 0 0