【Java設(shè)計模式】結(jié)構(gòu)型模式-裝飾模式

源代碼:https://gitee.com/AgentXiao/DecroatorPattern
要點:
1监透、裝飾模式解決的問題
2、裝飾模式的各個模塊實現(xiàn)
3航唆、裝飾模式的優(yōu)缺點
4胀蛮、裝飾模式和橋接模式的區(qū)別

一、場景引入

場景引入

如上圖所示糯钙,有一個狗(Dog)類粪狼,下面有三個子類,分別是會飛的狗(FlyDog)任岸、會游泳的狗(SwimDog)再榄、會跑的狗(RunDog)。假設(shè)此時三個子類都是單一功能的享潜,也就說FlyDog只會飛困鸥,游泳和跑步都不會。

如果此時需要一個既會飛也會跑的狗剑按,我們可以通過繼承的方式實現(xiàn)疾就,一次類推澜术,可以得到:

繼承具有新功能的狗

這顯然不是最好的方法!當(dāng)功能非常多時猬腰,需要繼承父類的子類數(shù)量將會大大增加瘪板!而裝飾模式就是解決這個問題的一種設(shè)計模式。

二漆诽、裝飾模式

裝飾模式是一種用于代替繼承的技術(shù),無需通過繼承增加子類就能夠擴展對象的新功能锣枝。使用對象的組合關(guān)系(區(qū)分于“組合設(shè)計模式”)代替繼承關(guān)系厢拭,避免類型體系的快速膨脹。

簡單地說撇叁,裝飾模式用于動態(tài)增加一個對象的新功能供鸠,或成為功能增強。

裝飾模式實現(xiàn)細節(jié):

裝飾模式實現(xiàn)細節(jié).png

(1)抽象構(gòu)建角色Component陨闹。這是真實對象和裝飾對象都需要實現(xiàn)的接口楞捂,便于客戶端可以使用相同的方式交互裝飾對象和真實對象,指上文的Dog趋厉。
(2)真實對象ConcreteComponent寨闹。具體需要裝飾的對象,定義為MyDog君账。
(3)裝飾對象Decorator繁堡。持有一個抽象構(gòu)件的引用(核心)。裝飾對象接受所有客戶端的請求乡数,并把這些請求通過引用轉(zhuǎn)發(fā)給真實對象椭蹄。這樣,就能在真實對象調(diào)用前后增加新的功能净赴,定義為SuperDog绳矩。
(4)具體裝飾對象ConcreteDecorator:指上文的Fly、Swim玖翅、Run翼馆。

三、裝飾模式的實現(xiàn)

1烧栋、抽象角色

/**
 * @InterfaceName Dog
 * @Description 抽象構(gòu)建角色
 * @Author xwd
 * @Date 2018/10/25 9:52
 */
public interface Dog {
    /**
     * @MethodName showPower
     * @Descrition 展示能力
     * @Param []
     * @return void
     */
    void showPower();
}

2写妥、具體角色

/**
 * @ClassName MyDog
 * @Description 具體對象
 * @Author xwd
 * @Date 2018/10/25 9:53
 */
public class MyDog implements Dog{
    @Override
    public void showPower() {
        System.out.println("我還沒有什么能力!");
    }
}

3审姓、裝飾角色(核心)

/**
 * @ClassName SuperDog
 * @Description 裝飾對象
 * @Author xwd
 * @Date 2018/10/25 9:54
 */
public class SuperDog implements Dog{
    protected Dog dog;//持有抽象構(gòu)建角色的引用

    public SuperDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public void showPower() {
        dog.showPower();
    }
}

4珍特、具體的裝飾角色

/**
 * @ClassName Fly
 * @Description 飛行能力
 * @Author xwd
 * @Date 2018/10/25 9:57
 */
public class Fly extends SuperDog{
    public Fly(Dog dog) {
        super(dog);
    }

    @Override
    public void showPower() {
        super.showPower();
        System.out.println("我具備飛行功能!");
    }
}
/**
 * @ClassName Run
 * @Description 奔跑能力
 * @Author xwd
 * @Date 2018/10/25 9:57
 */
public class Run extends SuperDog{
    public Run(Dog dog) {
        super(dog);
    }

    @Override
    public void showPower() {
        super.showPower();
        System.out.println("我具備奔跑功能魔吐!");
    }
}
/**
 * @ClassName Swim
 * @Description 游泳能力
 * @Author xwd
 * @Date 2018/10/25 9:57
 */
public class Swim extends SuperDog{
    public Swim(Dog dog) {
        super(dog);
    }

    @Override
    public void showPower() {
        super.showPower();
        System.out.println("我具備游泳功能扎筒!");
    }
}

5莱找、測試

/**
 * @ClassName Client
 * @Description 測試裝飾模式
 * @Author xwd
 * @Date 2018/10/25 9:59
 */
public class Client {
    public static void main(String[] args) {

        //原生態(tài)的狗,還沒有什么能力
        Dog dog = new MyDog();
        dog.showPower();
        System.out.println("*********************");

        //添加了裝飾模式的狗嗜桌,但是還沒有添加具體功能
        SuperDog superDog = new SuperDog(dog);
        superDog.showPower();
        System.out.println("*********************");

        //添加了飛行能力的狗
        SuperDog flyDog = new Fly(dog);
        flyDog.showPower();
        System.out.println("*********************");

        //添加了游泳能力的狗
        SuperDog swimDog = new Swim(dog);
        swimDog.showPower();
        System.out.println("*********************");

        //既添加了飛行能力又添加了奔跑能力的狗
        SuperDog runDog = new Run(dog);
        SuperDog fsDog = new Fly(runDog);
        fsDog.showPower();
        System.out.println("*********************");
    }
}

6奥溺、測試結(jié)果

測試結(jié)果

由此可見,需要為一個對象添加新功能時骨宠,只需要建立這個功能浮定,將具體對象傳入。如果傳入的對象是已經(jīng)具備某些功能的层亿,就相當(dāng)遠在那個基礎(chǔ)上添加新的功能桦卒。

四、開發(fā)中使用的場景

  • IO中輸入流和輸出流的設(shè)計匿又。
  • Swing包中圖形界面構(gòu)件功能方灾。
  • Servlet API 中提供了一個request對象的Decorator設(shè)計模式的默認實現(xiàn)類HttpServletRequestWrapper,HttpServletRequestWrapper類碌更,增強了request對象的功能裕偿。
  • Struts2中,request痛单,response,session對象的處理嘿棘。

在這里只解釋其中一種:
在IO流中,抽象構(gòu)建對象是InputStream桦他、OutputStream蔫巩、Reader、Writer快压。

真實對象是FileInputStream圆仔、FileOutputStream。

真實對象

裝飾對象是FilterInputStream蔫劣、FilterOutputStream坪郭。

裝飾對象

具體的裝飾對象:BufferedOutputStream、BufferedInputStream等脉幢。

繼承裝飾對象
構(gòu)造器中傳入抽象構(gòu)建對象

五歪沃、總結(jié)

1、功能

裝飾模式(Decorator)也叫包裝器模式(Wrapper)嫌松。

裝飾模式降低系統(tǒng)的耦合度沪曙,可以動態(tài)的增加或刪除對象的職責(zé),并使得需要裝飾的具體構(gòu)建類和具體裝飾類可以獨立變化萎羔,以便增加新的具體構(gòu)建類和具體裝飾類液走。

2、優(yōu)點

  • 擴展對象功能,比繼承靈活缘眶,不會導(dǎo)致類個數(shù)急劇增加嘱根。
  • 可以對一個對象進行多次裝飾,創(chuàng)造出不同行為的組合巷懈,得到功能更加強大的對象该抒。
  • 具體構(gòu)建類和具體裝飾類可以獨立變化,用戶可以根據(jù)需要自己增加新的具體構(gòu)件子類和具體裝飾子類顶燕。

3凑保、缺點

  • 產(chǎn)生很多小對象。大量小對象占據(jù)內(nèi)存涌攻,一定程度上影響性能愉适。
  • 裝飾模式易于出錯,調(diào)試排查比較麻煩癣漆。

4、裝飾模式和橋接模式的區(qū)別

兩個模式都是為了解決過多子類對象問題剂买。但他們的誘因不一樣惠爽。

  • 橋接模式是對象自身現(xiàn)有機制沿著多個維度變化。
  • 裝飾模式是為了增加新的功能瞬哼。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婚肆,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坐慰,更是在濱河造成了極大的恐慌较性,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件结胀,死亡現(xiàn)場離奇詭異赞咙,居然都是意外死亡,警方通過查閱死者的電腦和手機糟港,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門攀操,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人秸抚,你說我怎么就攤上這事速和。” “怎么了剥汤?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵颠放,是天一觀的道長。 經(jīng)常有香客問我吭敢,道長碰凶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮痒留,結(jié)果婚禮上谴麦,老公的妹妹穿的比我還像新娘。我一直安慰自己伸头,他們只是感情好匾效,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著恤磷,像睡著了一般面哼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扫步,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天魔策,我揣著相機與錄音,去河邊找鬼河胎。 笑死闯袒,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的游岳。 我是一名探鬼主播政敢,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼胚迫!你這毒婦竟也來了喷户?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤访锻,失蹤者是張志新(化名)和其女友劉穎褪尝,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體期犬,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡河哑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了龟虎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灾馒。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖遣总,靈堂內(nèi)的尸體忽然破棺而出睬罗,到底是詐尸還是另有隱情,我是刑警寧澤旭斥,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布容达,位于F島的核電站,受9級特大地震影響垂券,放射性物質(zhì)發(fā)生泄漏花盐。R本人自食惡果不足惜羡滑,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望算芯。 院中可真熱鬧柒昏,春花似錦、人聲如沸熙揍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽届囚。三九已至有梆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間意系,已是汗流浹背泥耀。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蛔添,地道東北人痰催。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像迎瞧,于是被迫代替她去往敵國和親陨囊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360