裝飾者模式(包裝一個(gè)對(duì)象,來提供新的行為)

源碼地址 https://github.com/DingMouRen/DesignPattern
裝飾者模式.png
  • Component:抽象組件,可以是一個(gè)接口或者抽象類距糖,是被裝飾的原始對(duì)象缸剪。
  • ConcreteComponent:組件具體實(shí)現(xiàn)類唬渗。該類是Component類的基本實(shí)現(xiàn),也是我們裝飾的具體對(duì)象撑蒜。
  • Decorator:抽象裝飾者狸眼。它承擔(dān)的職責(zé)是為了裝飾組件對(duì)象,其內(nèi)部一定要有一個(gè)指向組件對(duì)象的引用微王。在多數(shù)情況下,該類為抽象類激才,需要根據(jù)不同的裝飾邏輯實(shí)現(xiàn)不同的具體子類东帅。如果裝飾邏輯單一靠闭,只有一個(gè)情況下我們可以省略該類直接作為具體的裝飾者。
  • ConcreteDecoratorA:裝飾者具體實(shí)現(xiàn)類,只是對(duì)抽象裝飾者作出具體的實(shí)現(xiàn)蟀悦。
定義

裝飾者模式動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)孙乖。在增加功能方面鼓拧,裝飾者模式比生成子類更為靈活。

使用場(chǎng)景
  • 在不影響其他對(duì)象的情況下,以動(dòng)態(tài)、透明的方式給單個(gè)對(duì)象添加功能
  • 處理可以撤銷的職責(zé)
  • 當(dāng)不能采用生成子類的方式進(jìn)行擴(kuò)展功能時(shí)都哭。1.為類擴(kuò)展功能造成產(chǎn)生大量子類,子類數(shù)目爆炸性增長(zhǎng)穆趴。2.不能生成子類的情況,比如被final修飾的類
協(xié)作

Decorator將請(qǐng)求轉(zhuǎn)發(fā)給它的Component對(duì)象,并有可能在轉(zhuǎn)發(fā)請(qǐng)求前后執(zhí)行一些附加的動(dòng)作化戳,也就是想要添加的新行為递鹉。

舉個(gè)栗子

不管男的女的都是要穿衣服的,我們抽象成一個(gè)抽象類Person却盘,行為就是穿衣服,定義一個(gè)穿衣服的抽象方法dressed(),定義兩個(gè)類Boy、Girl分別繼承Person類,它們只有一個(gè)行為。假設(shè)Boy Girl都通過調(diào)用自己實(shí)現(xiàn)的dressed()方法竹挡,已經(jīng)穿了一件衣服,可是人不能只穿一件衣服吧(o)/~,但是我們不想去修改Boy Gril的對(duì)象,同時(shí)讓創(chuàng)建出來的這兩個(gè)實(shí)例對(duì)象能穿更多的衣服,也就是說在不影響對(duì)象的情況下贤重,為對(duì)象添加功能滚停。好啦镰吵,可以開始使用裝飾者模式了。我們定義一個(gè)裝飾的抽象類PersonCloth勺馆,讓它繼承抽象組件Person類悲柱,同時(shí)我們讓PersonCloth類持有一個(gè)Person類的引用,通過構(gòu)造器傳入。因?yàn)槔^承了Person類派任,就要實(shí)現(xiàn)dressed()這個(gè)抽象方法颤诀,里面的具體實(shí)現(xiàn)自然是Person類的引用調(diào)用dressed()屈暗,這就是保存這個(gè)引用的主要原因,可以方便的調(diào)用具體被裝飾對(duì)象的dressed()方法(java運(yùn)行時(shí)類型判斷)『偌埽現(xiàn)在我們要定義裝飾者的具體實(shí)現(xiàn)對(duì)象,定義CheapCloth類繼承PersonCloth類,實(shí)現(xiàn)dressed()方法西乖,這里面有一個(gè)super.dressed()這就是被裝飾對(duì)象自己原來的實(shí)現(xiàn),我們想添加的行為怎么辦呢?只要在CheapCloth這個(gè)具體裝飾對(duì)象中定義新的行為矫膨,然后在super.dressed()前或者后調(diào)用就可以了谊娇,這樣就添加了功能攀例,調(diào)用的時(shí)候自然調(diào)用的是這個(gè)裝飾者對(duì)象CheapCloth的dressed()方法。就好像通過CheapCloth類包裹了Boy類一樣垛吗,我們沒有動(dòng)Boy這樣的具體組件對(duì)象,也沒有使用繼承可能會(huì)造成類爆炸的方式。

//抽象組件類:類Person定義一個(gè)穿衣的抽象方法
public abstract class Person {
    public abstract void dressed();
}
//組件具體實(shí)現(xiàn)類:需要被裝飾的具體對(duì)象
public class Boy extends Person {
    @Override
    public void dressed() {
        System.out.println(getClass().getSimpleName()+"穿牛仔褂");
    }
}

//裝飾抽象類:表示人要穿的衣服
public abstract class PersonCloth  extends Person{
    /**
     * 保持一個(gè)Person類的引用狼牺,方便調(diào)用具體被裝飾對(duì)象中的方法
     * 這樣可以在不破壞原類層次結(jié)構(gòu)的情況下為類添加一些功能是钥,只需要在被裝飾對(duì)象的相應(yīng)方法
     * 前或后增加相應(yīng)的邏輯功能就行。
     * 如果裝飾物只有一個(gè)的話领铐,不必聲明一個(gè)抽象類作為裝飾者抽象的提取。只要定義一個(gè)普通的類表示裝飾者就行
     */
    private Person person;

    public PersonCloth(Person person) {
        this.person = person;
    }

    @Override
    public void dressed() {
        person.dressed();//調(diào)用Person類型的dressed()方法
    }

    public Person getPerson() {
        return person;
    }
}

//具體裝飾者
public class CheapCloth extends PersonCloth {

    public CheapCloth(Person person) {
        super(person);
    }

    @Override
    public void dressed() {
        //原來具體組件實(shí)現(xiàn)
        super.dressed();
        //添加的新行為的具體實(shí)現(xiàn)
        dressShorts();
    }

    private void dressShorts(){
        System.out.println(getPerson().getClass().getSimpleName()+"穿短褲");
    }
}

public static void main(String[] args) {
        //創(chuàng)建被裝飾對(duì)象
        Person person = new Boy();
        //給他穿便宜衣服
        PersonCloth clothCheap = new CheapCloth(person);
        clothCheap.dressed();
        //穿貴的衣服
        PersonCloth clothExpensive = new ExpensiveCloth(person);
        clothExpensive.dressed();


        Person girl = new Girl();
        PersonCloth clothCheapGirl = new CheapCloth(girl);
        clothCheapGirl.dressed();
    }

使用

public static void main(String[] args) {
        //創(chuàng)建被裝飾對(duì)象
        Person person = new Boy();
        //給他穿便宜衣服
        PersonCloth clothCheap = new CheapCloth(person);
        clothCheap.dressed();
        //穿貴的衣服
        PersonCloth clothExpensive = new ExpensiveCloth(person);
        clothExpensive.dressed();


        Person girl = new Girl();
        PersonCloth clothCheapGirl = new CheapCloth(girl);
        clothCheapGirl.dressed();
    }
總結(jié)

裝飾者模式為所裝飾的對(duì)象增加功能糠亩,而不使用繼承的方式,也不會(huì)影響被裝飾對(duì)象党远。有的時(shí)候會(huì)跟代理模式混淆削解,代理模式做的不是增加功能,而是對(duì)代理的對(duì)象進(jìn)行控制沟娱。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末氛驮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子济似,更是在濱河造成了極大的恐慌矫废,老刑警劉巖盏缤,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蓖扑,居然都是意外死亡唉铜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門律杠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來潭流,“玉大人,你說我怎么就攤上這事柜去』壹担” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵嗓奢,是天一觀的道長(zhǎng)讼撒。 經(jīng)常有香客問我,道長(zhǎng)股耽,這世上最難降的妖魔是什么根盒? 我笑而不...
    開封第一講書人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮物蝙,結(jié)果婚禮上炎滞,老公的妹妹穿的比我還像新娘。我一直安慰自己诬乞,他們只是感情好厂榛,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著丽惭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辈双。 梳的紋絲不亂的頭發(fā)上责掏,一...
    開封第一講書人閱讀 52,457評(píng)論 1 311
  • 那天咕晋,我揣著相機(jī)與錄音涡拘,去河邊找鬼。 笑死亡蓉,一個(gè)胖子當(dāng)著我的面吹牛证芭,可吹牛的內(nèi)容都是我干的瞳浦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼废士,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼叫潦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起官硝,我...
    開封第一講書人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤矗蕊,失蹤者是張志新(化名)和其女友劉穎短蜕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傻咖,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朋魔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卿操。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片警检。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖害淤,靈堂內(nèi)的尸體忽然破棺而出扇雕,到底是詐尸還是另有隱情,我是刑警寧澤筝家,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布洼裤,位于F島的核電站,受9級(jí)特大地震影響溪王,放射性物質(zhì)發(fā)生泄漏腮鞍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一莹菱、第九天 我趴在偏房一處隱蔽的房頂上張望移国。 院中可真熱鬧,春花似錦道伟、人聲如沸迹缀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祝懂。三九已至,卻和暖如春拘鞋,著一層夾襖步出監(jiān)牢的瞬間砚蓬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來泰國打工盆色, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留灰蛙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓隔躲,卻偏偏與公主長(zhǎng)得像摩梧,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宣旱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

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

  • 1 場(chǎng)景問題# 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
  • 設(shè)計(jì)模式匯總 一、基礎(chǔ)知識(shí) 1. 設(shè)計(jì)模式概述 定義:設(shè)計(jì)模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 3,949評(píng)論 1 15
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法驾霜,類相關(guān)的語法案训,內(nèi)部類的語法,繼承相關(guān)的語法粪糙,異常的語法强霎,線程的語...
    子非魚_t_閱讀 31,664評(píng)論 18 399
  • 放慢腳步,在校園 把呼吸折疊于心蓉冈, 我看見 每一朵花都在奔跑 花影亂 雙手捧出 風(fēng)——舞動(dòng)多彩的眼睛 48顆柔軟...
    雪兒金閱讀 161評(píng)論 0 0
  • 蘇寒此話一出城舞,大廳當(dāng)中立刻寂靜了下來。 顯然誰都沒有想到寞酿,以蘇寒此刻的情況家夺,還敢這般對(duì)蘇云琛說話。 只有坐在主...
    魔筆判官閱讀 403評(píng)論 0 1