閑扯設(shè)計(jì)模式之裝飾者模式

前言

最近看了一部英劇《黑鏡》,片中講述科技與人性碰撞可能帶來(lái)的一系列社會(huì)負(fù)影響,包括泛娛樂(lè)社會(huì)對(duì)底層人民精神的麻木作用、人工智能可能帶來(lái)的將短期痛苦無(wú)限延長(zhǎng)等等影響夷都,感慨萬(wàn)分,在這里極力推薦大伙看看這部神劇吴旋。不扯了损肛,下面開始聊聊裝飾者模式。

定義

先給出裝飾者模式的定義(來(lái)自維基百科):裝飾者模式荣瑟,是面向?qū)ο缶幊填I(lǐng)域中,一種動(dòng)態(tài)地往一個(gè)類中添加新的行為的設(shè)計(jì)模式摩泪。就功能而言笆焰,修飾模式相比生成子類更為靈活,這樣可以給某個(gè)對(duì)象而不是整個(gè)類添加一些功能见坑。裝飾者模式出現(xiàn)的意義是解決了運(yùn)行時(shí)類功能的拓展嚷掠,使得可以在運(yùn)行時(shí)進(jìn)行任一功能組合而不是需要為每種組合設(shè)計(jì)一個(gè)類(參見javaIO的設(shè)計(jì))

相關(guān)設(shè)計(jì)原則

裝飾者模式遵循開放-關(guān)閉原則捏检,及類應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉的原則不皆。也就是說(shuō)我們?cè)陧?xiàng)目開發(fā)過(guò)程中應(yīng)盡量減少對(duì)已完成部分的修改贯城,把重心放在功能的拓展至上。

基本結(jié)構(gòu)

這里我們通過(guò)UML類圖來(lái)直觀地理解裝飾者模式的結(jié)構(gòu)霹娄。如圖:


Decorator UML類圖

這里有幾個(gè)地方需要注意一下:裝飾者與被裝飾者繼承自同一個(gè)抽象類或者接口(Component)的原因:我們利用多態(tài)能犯,通過(guò)將裝飾者與被裝飾者繼承自同一父抽象類或者接口實(shí)現(xiàn)被繼承者在被裝飾后類型不變的目的,也可以實(shí)現(xiàn)被裝飾者相互修飾的目的犬耻。第二個(gè)需要注意的是踩晶,每個(gè)裝飾者必須寫好它們的描述屬性,便于后期檢查維護(hù)枕磁。

實(shí)例

下面利用一個(gè)例子來(lái)講解裝飾者模式的使用方法渡蜻。下面的例子純屬瞎扯我們的主角VinceBarry是一名NBA新秀,他想要提高自己的籃球能力计济,通過(guò)學(xué)習(xí)模仿一些巨星的技巧是他最終選擇的方案茸苇。于是他先學(xué)習(xí)了杜蘭特的跳投技巧,然后不過(guò)癮又學(xué)習(xí)了庫(kù)里的三分球和歐文的運(yùn)球技巧沦寂,最終他的能力達(dá)到了130超過(guò)了2k的上限……扯遠(yuǎn)了学密,下面我們利用代碼來(lái)為VinceBarry增加能力。

創(chuàng)建組件抽象類

首先我們需要一個(gè)父抽象類凑队,這里我們命名為PlayBasketball则果。下面是他的具體實(shí)現(xiàn):

abstract class PlayBasketball {
    String description;
    public String getDescription(){
        return description;
    }
    public abstract int score();
}

這里我們?yōu)閂inceBarry和技能們抽象出了兩個(gè)共有的屬性:描述和技能值。從這里也可以看出這個(gè)抽象類應(yīng)該是裝飾者和被裝飾者共有屬性方法的容器漩氨。

創(chuàng)建裝飾者抽象類

下面我們?cè)賱?chuàng)建技能包的抽象類(對(duì)照上面的UML類圖)西壮,我們?nèi)∶麨锽asketballSkill,下面貼上代碼:

abstract class BasketballSkill extends PlayBasketball {
    public abstract String getDescription();
}

這個(gè)類繼承自父抽象類PlayBasketball叫惊,類中有一個(gè)方法用于描述不同的裝飾者款青,這個(gè)是裝飾者必須實(shí)現(xiàn)的方法。

創(chuàng)建各種裝飾者

接下來(lái)就是創(chuàng)建各種技能了霍狰,這里我創(chuàng)建了三個(gè)技能:CurryThreePoint抡草,DurantJumpShoot,IrvingDribbling蔗坯。由于后兩個(gè)代碼與第一個(gè)類似康震,我就只展示CurryThreePoint這項(xiàng)技能的代碼了。

class CurryThreePoint extends BasketballSkill {
    private PlayBasketball playBasketball;

    CurryThreePoint(PlayBasketball playBasketball) {
        this.playBasketball = playBasketball;
    }

    @Override
    public String getDescription() {
        return playBasketball.getDescription()+" has curry's three point skill";
    }

    @Override
    public int score() {
        return 40 + playBasketball.score();
    }
}

下面闡述一下這個(gè)類中的幾個(gè)關(guān)鍵點(diǎn):首先是繼承自裝飾者父類宾濒,所以必須重寫getDescription()方法腿短。然后我們重寫最關(guān)鍵的方法:score()。這個(gè)方法的特點(diǎn)是,將裝飾者中的特定行為與傳入的被裝飾者(也可能是裝飾者)的行為進(jìn)行疊加橘忱,這里的裝飾者是我們?cè)跇?gòu)造方法中傳入的Playbasketball類型的對(duì)象赴魁。通過(guò)這種方式實(shí)現(xiàn)了對(duì)象行為的修改或功能的拓展。也就是在這里我們?yōu)閂inceBarry加上了庫(kù)里三分球的能力钝诚。

測(cè)試代碼

下面我們測(cè)試一下整個(gè)流程(關(guān)于裝飾者的構(gòu)建颖御,在工廠和生成器模式中有更加優(yōu)秀的方案,日后再扯):

public class Court {
    public static void main(String[] args) {
        PlayBasketball vinceBarry = new VinceBarry();
        System.out.println(vinceBarry.getDescription() + " " + vinceBarry.score());
        vinceBarry = new DurantJumpShoot(vinceBarry);
        vinceBarry = new CurryThreePoint(vinceBarry);
        vinceBarry = new IrvingDribbling(vinceBarry);
        System.out.println(vinceBarry.getDescription() + " " + vinceBarry.score());
    }
}

輸出結(jié)果為


結(jié)果

總結(jié)

又到一學(xué)期快結(jié)束的時(shí)間段了凝颇,想想近來(lái)自己也沒(méi)學(xué)啥潘拱,贈(zèng)給自己一句話:就是干!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末祈噪,一起剝皮案震驚了整個(gè)濱河市泽铛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌辑鲤,老刑警劉巖盔腔,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異月褥,居然都是意外死亡弛随,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門宁赤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)舀透,“玉大人,你說(shuō)我怎么就攤上這事决左°倒唬” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵佛猛,是天一觀的道長(zhǎng)惑芭。 經(jīng)常有香客問(wèn)我,道長(zhǎng)继找,這世上最難降的妖魔是什么遂跟? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮婴渡,結(jié)果婚禮上幻锁,老公的妹妹穿的比我還像新娘。我一直安慰自己边臼,他們只是感情好哄尔,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著柠并,像睡著了一般究飞。 火紅的嫁衣襯著肌膚如雪置谦。 梳的紋絲不亂的頭發(fā)上堂鲤,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天亿傅,我揣著相機(jī)與錄音,去河邊找鬼瘟栖。 笑死葵擎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的半哟。 我是一名探鬼主播酬滤,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寓涨!你這毒婦竟也來(lái)了盯串?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤戒良,失蹤者是張志新(化名)和其女友劉穎体捏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糯崎,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡几缭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沃呢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片年栓。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖薄霜,靈堂內(nèi)的尸體忽然破棺而出某抓,到底是詐尸還是另有隱情,我是刑警寧澤惰瓜,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布否副,位于F島的核電站,受9級(jí)特大地震影響鸵熟,放射性物質(zhì)發(fā)生泄漏副编。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一流强、第九天 我趴在偏房一處隱蔽的房頂上張望痹届。 院中可真熱鬧,春花似錦打月、人聲如沸队腐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)柴淘。三九已至迫淹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間为严,已是汗流浹背敛熬。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留第股,地道東北人应民。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像夕吻,于是被迫代替她去往敵國(guó)和親诲锹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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

  • Iterator模式 (迭代器) 一個(gè)一個(gè)遍歷 一個(gè)集合類可以遵守 Iterator 協(xié)議涉馅,并實(shí)現(xiàn)一個(gè) Itera...
    SSBun閱讀 1,847評(píng)論 0 15
  • 設(shè)計(jì)原則: 少用繼承归园,多用組合 類應(yīng)該對(duì)擴(kuò)展開放,對(duì)修改關(guān)閉 目錄 本文的結(jié)構(gòu)如下: 什么是裝飾者模式 為什么要用...
    w1992wishes閱讀 1,189評(píng)論 0 7
  • 1 場(chǎng)景問(wèn)題# 1.1 復(fù)雜的獎(jiǎng)金計(jì)算## 考慮這樣一個(gè)實(shí)際應(yīng)用:就是如何實(shí)現(xiàn)靈活的獎(jiǎng)金計(jì)算稚矿。 獎(jiǎng)金計(jì)算是相對(duì)復(fù)雜...
    七寸知架構(gòu)閱讀 4,013評(píng)論 4 67
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法庸诱,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法盐捷,繼承相關(guān)的語(yǔ)法偶翅,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 31,664評(píng)論 18 399
  • 我家那幾頭豬碉渡,這句話莫名其妙就點(diǎn)綴在舌尖上舌聚谁,恰若輕輕淡淡的菠蘿味在唇齒間游走... 初...
    徵涯閱讀 233評(píng)論 0 1