設(shè)計(jì)模式——裝飾者模式

概述

定義
指在不改變現(xiàn)有對象結(jié)構(gòu)的情況下武花,動態(tài)地給該對象增加一些職責(zé)(即增加其額外功能)的模式圆凰。
看了網(wǎng)上的很多關(guān)于裝飾者模式的講解,都是一些什么關(guān)于咖啡算總價的例子体箕,起碼看的時候總是會把重心放到它的遞歸求總價上面专钉,而忘記了裝飾者的本質(zhì)是添加額外的功能。
剛好最近迷上了一款永劫無間的游戲累铅,個人覺得裝飾者模式似乎就像武器和魂玉之間的關(guān)系跃须。有了魂玉,武器就可以有一些特定的技能娃兽。我們以此為基礎(chǔ)來理解裝飾者模式菇民。

結(jié)構(gòu)

裝飾者(Decorator)模式中的角色:

  • 抽象構(gòu)件(Component)角色 :定義一個抽象接口以規(guī)范準(zhǔn)備接收附加責(zé)任的對象。(各種武器的父類——Weapon)
  • 具體構(gòu)件(Concrete Component)角色 :實(shí)現(xiàn)抽象構(gòu)件投储,通過裝飾角色為其添加一些職責(zé)第练。(具體武器——長槍)
  • 抽象裝飾(Decorator)角色 : 繼承或?qū)崿F(xiàn)抽象構(gòu)件,并包含具體構(gòu)件的實(shí)例玛荞,可以通過其子類擴(kuò)展具體構(gòu)件的功能娇掏。(裝飾者)
  • 具體裝飾(ConcreteDecorator)角色 :實(shí)現(xiàn)抽象裝飾的相關(guān)方法,并給具體構(gòu)件對象添加附加的責(zé)任勋眯。(特定技能——魂玉)

舉例

1婴梧、定義抽象構(gòu)件
這里使用抽象類或者接口都是可以的

public abstract class Weapon {
    private String name;

    public Weapon(String name){
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public abstract String display();
}

2、定義具體構(gòu)件
這里可以定義多個具體武器客蹋,由于個人比較喜歡長槍志秃,所以只定義了一個長槍,繼承武器類嚼酝,并實(shí)現(xiàn)抽象方法

public class Pike extends Weapon{
    public Pike() {
        super("長槍");
    }

    @Override
    public String display() {
        return "長槍展示:";
    }
}

3、定義裝飾者
裝飾者類為裝飾者模式的核心竟坛,它繼承武器類闽巩,并擁有一個構(gòu)件對象,可以認(rèn)為這個構(gòu)件對象才是武器本體担汤。在我看來涎跨,裝飾者是為了把魂玉‘’裝到“武器上,所以必須有一個武器本體崭歧。

public abstract class Decorator extends Weapon{
    // 持有一個構(gòu)件對象
    protected Weapon weapon;

    public Decorator(String name,Weapon weapon) {
        super(name);
        this.weapon = weapon;
    }

    @Override
    public String display() {
        return weapon.display() + " 裝配: " + getName() + " 獲得能力: " + bisha();
    }

    // 對組件進(jìn)行裝飾的抽象方法
    public abstract String bisha();
}

4隅很、具體裝飾角色
定義了具體的功能,比如這個魂玉率碾,使武器擁有了bisha叔营。

public class Jade1 extends Decorator{

    public Jade1(Weapon weapon) {
        super("魂玉1",weapon);
    }

    @Override
    public String bisha() {
       return "大圣游";
    }
}
public class Jade2 extends Decorator{
    public Jade2(Weapon weapon) {
        super("魂玉2",weapon);
    }

    @Override
    public String bisha() {
        return "狂狼怒濤";
    }
}

5屋彪、客戶端

public class AppTest {
    public static void main(String[] args) {
        Weapon pike  = new Pike();
        pike= new Jade1(pike);
        pike= new Jade2(pike);
        System.out.println(pike.display());
    }
}

這里使用的時候有點(diǎn)類似javaIO流的使用,因?yàn)閖ava的IO流的設(shè)計(jì)就是使用了裝飾者模式绒尊。
長槍展示: 裝配: 魂玉1 獲得能力: 大圣游 裝配: 魂玉2 獲得能力: 狂狼怒濤

類圖

image.png

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

  • 飾者模式可以帶來比繼承更加靈活性的擴(kuò)展功能畜挥,使用更加方便,可以通過組合不同的裝飾者對象來獲取具有不同行為狀態(tài)的多樣化的結(jié)果婴谱。裝飾者模式比繼承更具良好的擴(kuò)展性蟹但,完美的遵循開閉原則,繼承是靜態(tài)的附加責(zé)任谭羔,裝飾者則是動態(tài)的附加責(zé)任华糖。
  • 裝飾類和被裝飾類可以獨(dú)立發(fā)展,不會相互耦合瘟裸,裝飾模式是繼承的一個替代模式客叉,裝飾模式可以動態(tài)擴(kuò)展一個實(shí)現(xiàn)類的功能。

源碼分析

如上面所說景描,裝飾者模式在javaIO流中應(yīng)用比較廣泛十办,像我們平常常見的BufferedInputStream就是一個具體裝飾者,它提供的功能就是添加緩沖區(qū)超棺,更好的讀取流的內(nèi)容向族。先來看一下BufferedInputStream的繼承關(guān)系


image.png

對比上面的類圖看這個關(guān)系是不是更加明顯呢?
Decorator就對應(yīng)著FilterInputStream


image.png

在FilterInputStream里也聚合了一個InputStream
再看看BufferedInputStream是如何使用的
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\bis.txt"));
        byte[] bytes = new byte[1024];
        int read = bis.read(bytes);
        System.out.println(bytes+":"+read);

這里沒有直接new一個InputStream棠绘,而是new一個FileInpuStream件相,畢竟FileInputStream也是繼承InputStream。FileInputStream讀取在某些情況下是阻塞的氧苍,這里使用緩沖區(qū)來讀取既能提高讀取效率(因?yàn)榫彌_區(qū)在內(nèi)存里)夜矗,又能避免阻塞(BufferInputStream的read是非阻塞的)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市让虐,隨后出現(xiàn)的幾起案子紊撕,更是在濱河造成了極大的恐慌,老刑警劉巖赡突,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件对扶,死亡現(xiàn)場離奇詭異,居然都是意外死亡惭缰,警方通過查閱死者的電腦和手機(jī)浪南,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漱受,“玉大人络凿,你說我怎么就攤上這事。” “怎么了絮记?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵摔踱,是天一觀的道長。 經(jīng)常有香客問我到千,道長昌渤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任憔四,我火速辦了婚禮膀息,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘了赵。我一直安慰自己潜支,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布柿汛。 她就那樣靜靜地躺著冗酿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪络断。 梳的紋絲不亂的頭發(fā)上裁替,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機(jī)與錄音貌笨,去河邊找鬼弱判。 笑死,一個胖子當(dāng)著我的面吹牛锥惋,可吹牛的內(nèi)容都是我干的昌腰。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼膀跌,長吁一口氣:“原來是場噩夢啊……” “哼遭商!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捅伤,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤劫流,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丛忆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體祠汇,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年蘸际,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片徒扶。...
    茶點(diǎn)故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡粮彤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情导坟,我是刑警寧澤屿良,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站惫周,受9級特大地震影響尘惧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜递递,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一喷橙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧登舞,春花似錦贰逾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至践叠,卻和暖如春言缤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背禁灼。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工管挟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人匾二。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓哮独,卻偏偏與公主長得像,于是被迫代替她去往敵國和親察藐。 傳聞我的和親對象是個殘疾皇子皮璧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評論 2 349

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