1. 程式人生 > >Java設計模式--裝飾者模式【Decorator Pattern】

Java設計模式--裝飾者模式【Decorator Pattern】

      有時,你想要在程式執行期間為某個物件組合新的行為,且在某種情況下,你需要物件的行為發生一些細小的變化,並且這些變化可以自由組合。這時,裝飾者模式就可以滿足這種需求。

 所謂裝飾者模式,也叫修飾者模式、裝飾器模式,意圖是在執行時組合操作的新變化,即動態地給一個物件新增一些額外的職責。

 裝飾模式在中國使用的那實在是多,中國的文化是中庸文化,中國人都比較“愛面子”,說話做事呢都不能太直接,必須給對方留有餘地。比如某個陽光燦爛的清晨,領導興高采烈精神煥發地出現在你面前,你擡頭一看,哎,換髮型了,怎麼這麼挫?但是你還是會一遍又一遍地壓抑自己的內心,面帶微笑說,領導今天真是帥氣!領導一聽,哎,這個員工挺有眼光,然後春風滿面揚長而去。若你不識擡舉,跟領導說,你這個髮型怎麼這麼難看,像個糟老頭!我敢保證,你離辭職不遠了。。。

 再來說說鄰居的阿姨有個女兒,名叫小紅,芳齡28,生的是亭亭玉立,貌美如花,眼看著閨蜜,同學一個個結婚生子,而小紅卻依然孑然一身,阿姨愁得每天吃不好睡不著。然後就拖著範大媽給介紹物件,範大媽一想,哎,我剛好有個同學的兒子華哥還單著,要不給介紹給小紅把,年齡大點,但是多會照顧人呢。。。

 我們就來說說這個華哥,範大媽一想,可不能直接說年齡、身高、長相,那敢情小花看不上怎麼辦?她就尋思著多給小花說說華哥的“優異”條件,這樣一修飾,華哥就是難得的”鑽石王老五”啦,小花不要還有小劉呢。

 範大媽簡單畫了個圖,是這樣的:

  定義了男人的抽象類,然後有個普通男人實現類,再有個高學歷的男人實現類,再有好工作男人實現類,再有好家境男人的實現類,看看這些類:

package com.pattern.decorator.v1;
/**
 * 那男人說了,把我的條件跟人家說說
 * 同意就交往,不行就算了,給句痛快話
 * @author 
 *
 */
public abstract class Man {
    public abstract void showAppearance();//外在條件
    public abstract void appointment(boolean yesOrNo);//是否同意呢
}
package com.pattern.decorator.v1;
/**
 * 外在條件太一般了,咋整?
 * @author 
 *
 */
public class NormalMan extends Man {

	@Override
	public void showAppearance() {
        System.out.println("年齡40,身高1.68cm,長相一般,有點黑,好在不是歪瓜裂棗...");
	}
	@Override
	public void appointment(boolean yesOrNo){
		if(yesOrNo){
			System.out.println("同意啦,交往吧!");
		}else{
			System.out.println("太挫了,休想!");
		}
	}
}
package com.pattern.decorator.v1;
/**
 * 高智商高學歷,不錯哦,繼續看看。。。
 * @author 
 *
 */
public class GoodEducationMan extends NormalMan {

 private void showEducation(){
	 System.out.println("清華大學博士哦...");
 }
 @Override
public void showAppearance() {
	 this.showEducation();
	 super.showAppearance();
}
}
package com.pattern.decorator.v1;
/**
 * 男人40一枝花,這條件也是沒誰了,老張閨女不行還設有老李家呢
 * @author 
 *
 */
public class GoodWorkMan extends GoodEducationMan {
 @Override
public void showAppearance() {
	 this.showWork();
	 super.showAppearance();
}
private void showWork(){
	 System.out.println("某證券公司部門經理...");
 }
}
package com.pattern.decorator.v1;
/**
 * 家境還這麼好,老人無負擔,誰看不上誰無腦
 * @author 
 *
 */
public class GoodParentsMan extends GoodWorkMan{
  private void showParents(){
	  System.out.println("爸媽都是公務員,拿著退休金在家樂呵呵....");
  }

@Override
public void showAppearance() {
	this.showParents();
	super.showAppearance();
}  
}
 然後範大媽就跟小紅說,這個男人呀,是個高材生博士,在某證券公司當老總,父母是公務員,雖然年齡稍大,長相身高都一般,那都不是事兒呀,你考慮考慮?
package com.pattern.decorator.v1;
/**
 * 老張閨女相親錄
 * @author 
 *
 */
public class Test_DatingWoman {
   public static void main(String[] args){
	   Man man=new GoodParentsMan();////高學歷 好工作 家境好 外在條件
	   man.showAppearance();//相親女看條件
	   man.appointment(true);//然後覺得很開心啊,不錯啊,同意同意
   }
}
  以上是通過“繼承”的方式確實解決了這個問題,但是現實的情況很複雜的,可能小紅聽範大媽說完學歷高後,就直接樂開花了,直接同意了,後面工作好,家境好都不需要了,或者小紅覺得比較在意工作,先說了工作就不用說別的了,那怎麼辦?繼續擴充套件類?你能擴充套件多少個類?這還是一個比較簡單的場景,一旦需要裝飾的條件非常的多,比如20 個,你還通過繼承來解決,你想想的子類有多少個?類與類之間的父子關係是怎樣?你是不是馬上就要崩潰了!

 好,你也看到通過繼承情況確實出現了問題,類爆炸,類的數量激增,光寫這些類不累死你才怪,而且還要想想以後維護怎麼辦,誰願意接收這麼一大堆類的維護哪?並且在面向物件的設計中,如果超過2 層繼承,你就應該想想是不是出設計問題了,是不是應該重新找一條道了,這是經驗值,不是什麼絕對的,繼承層次越多你以後的維護成本越多,問題這麼多,那怎麼辦?好辦,裝飾模式出場來解決這些問題,我們先來看類圖:


  增加一個裝飾抽象類和三個實現類,其中ManDecorator的作用是封裝Man類,看原始碼:

package com.pattern.decorator.v2;
/**
 * 鄰居阿姨看了直嘆氣,這條件,怎麼跟人家閨女說呢
 * 還是先把男人包裝下,不能直接說,不然就泡湯了
 * @author 
 *
 */
public abstract class ManDecorator extends Man {
	private Man man;

	public ManDecorator(Man man) {
		super();
		this.man = man;
	}

	@Override
	public void showAppearance() {
        this.man.showAppearance();
	}

	@Override
	public void appointment(boolean yesOrNo) {
        this.man.appointment(yesOrNo);
	}

}
package com.pattern.decorator.v2;
/**
 * 高智商高學歷,不錯哦,繼續看看。。。
 * @author 
 *
 */
public class GoodEducationDecorator extends ManDecorator {
	public GoodEducationDecorator(Man man){
    	super(man);
    }
	private void showEducation(){
		 System.out.println("清華大學博士哦...");
	}
	@Override
	public void showAppearance() {
		this.showEducation();
		super.showAppearance();
	}
}
package com.pattern.decorator.v2;
/**
 * 男人40一枝花,這條件也是沒誰了,老張閨女不行還設有老李家呢
 * @author 
 *
 */
public class GoodWorkDecorator extends ManDecorator {

	public GoodWorkDecorator(Man man) {
		super(man);
	}
    private void showWork(){
    	System.out.println("某證券公司部門經理...");
    }
	@Override
	public void showAppearance() {
		this.showWork();
		super.showAppearance();
	}
}
package com.pattern.decorator.v2;
/**
 * 家境還這麼好,老人無負擔,誰看不上誰無腦
 * @author 
 *
 */
public class GoodParentsDecorator extends ManDecorator {

	public GoodParentsDecorator(Man man) {
		super(man);
	}
	private void showParents(){
		  System.out.println("爸媽都是公務員,拿著退休金在家樂呵呵....");
	}
	@Override
	public void showAppearance() {
        this.showParents();
		super.showAppearance();
	}
}
然後範大媽找到小紅,就問問小紅的相親標準呀,然後根據她的品味一個條件一個條件地跟她說,直到她同意為止:
package com.pattern.decorator.v2;
/**
 * 老張閨女相親錄
 * @author 
 *
 */
public class Test_DatingWoman {
  public static void main(String[] args){
	  Man man=null;
	  man=new NormalMan();//外在條件
	  man=new GoodParentsDecorator(man);//家境好
	  man=new GoodEducationDecorator(man);//高學歷
	  man=new GoodWorkDecorator(man);//好工作
	  man.showAppearance();//相親女看條件,其實家境好,學歷高就暗自點頭了
	  man.appointment(true);//然後覺得很開心啊,不錯啊,同意同意
  }
}

  這就是裝飾者模式,裝飾者模式的通用類圖如下:

     

  看類圖,Component 是一個介面或者是抽象類,就是定義我們最核心的物件,也就是最原始的物件,比如上面的相親男,記住在裝飾模式中,必然有一個被提取出來最核心、最原始、最基本的介面或抽象類,就是Component。ConcreteComponent 這個是最核心、最原始、最基本的介面或抽象類的實現,你要裝飾的就是這個東西Decorator 一般是一個抽象類,做什麼用呢?實現介面或者抽象方法,它裡面可不一定有抽象的方法呀,在它的屬性裡必然有一個private 變數指向Component。ConcreteDecoratorA 和ConcreteDecoratorB 是兩個具體的裝飾類,你要把你最核心的、最原始的、最基本的東西裝飾城啥東西,上面的例子就是把一個比較平庸的男人裝飾成大家認可的成功男士。

 繼承和裝飾者模式的區別

 裝飾者模式是對繼承的有力補充,繼承是給一個類新增行為的比較有效的途徑。通過使用繼承,可以使得子類在擁有自身方法的同時,還可以擁有父類的方法。但是使用繼承是靜態的,在編譯的時候就已經決定了子類的行為,我們不便於控制增加行為的方式和時機。而裝飾者模式是動態組合組合關係的優勢就在於不會破壞類的封裝性,且具有較好的鬆耦合性,可以使系統更加容易維護。但是它的缺點就在於也要建立很多的物件。

裝飾者的使用場景

  1、在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責。

  2、需要動態地給一個物件增加功能,這些功能也可以動態地被撤銷。  當不能採用繼承的方式對系統進行擴充或者採用繼承不利於系統擴充套件和維護時。


相關推薦

Java設計模式--裝飾模式Decorator Pattern

      有時,你想要在程式執行期間為某個物件組合新的行為,且在某種情況下,你需要物件的行為發生一些細小的變化,並且這些變化可以自由組合。這時,裝飾者模式就可以滿足這種需求。  所謂裝飾者模式,也叫修飾者模式、裝飾器模式,意圖是在執行時組合操作的新變化,即動態地給一個物件

Java設計模式裝飾模式

解決 over 裝飾者模式 pack img 應該 ora 我們 lan 目錄      一、問題引入  二、設計原則  三、用裝飾者模式解決問題  四、裝飾者模式的特點  五、裝飾者模式的定義  六、裝飾者模式的實現  七、java.io包內的裝飾者模式

java設計模式--裝飾模式

照例搬一篇文章連線,我一般會選擇帶有uml圖的 方便理解,我只貼程式碼,因為我覺得別人理解的比我透徹,寫的比我好 http://www.cnblogs.com/stonefeng/p/5679638.html 裝飾者模式可以給物件新增一些額外的東西,設計模式那種書中舉例是星巴克的例子,如果每一種做

設計模式-裝飾模式(Decorator)

概述 定義 : 在不改變原有物件的基礎之上, 將功能附加到物件上 提供了比繼承更有彈性的替代方案(擴充套件原有物件功能) 又叫包裝器Wrapper, 介面卡模式也被稱之為包裝器 型別 : 結構型 適用場景 擴充套件一個類的功能或給一個類

Java設計模式-裝飾模式

定義: 裝飾者是在不改變物件的情況下動態給物件新增屬性和行為,將責任動態的附加在物件上。 與繼承有類似功能即擴充套件功能。 裝飾者模式與繼承的區別: **繼承:**在子類擴充套件功能的時候是靜態的,並且是已知需要擴充套件的功能,是在編譯時實現的。 **裝飾者模式:**比繼承更

從原始碼角度理解Java設計模式——裝飾模式

一、飾器者模式介紹 裝飾者模式定義:在不改變原有物件的基礎上附加功能,相比生成子類更靈活。 適用場景:動態的給一個物件新增或者撤銷功能。 優點:可以不改變原有物件的情況下動態擴充套件功能,可以使擴充套件的多個功能按想要的順序執行,以實現不同效果。 缺點:更多的類,使程式複雜 型別:結構型。 類圖

Java設計模式---裝飾模式(用生活例子解釋通過裝飾類物件對方法進行實現介面的方法增強)

裝飾者模式可以動態地給一個物件新增一些額外的職責。 就增加功能來說,Decorator模式相比生成子類更為靈活。 該模式的適用環境為: (1)在不影響其他物件的情況下,以動態、透明的方式給單個物件新增職責。 (2)處理那些可以撤消的職責。 (3)當不能採用生成子

設計模式——裝飾模式 Java原始碼

裝飾者模式,可以動態地把職責附加到已有的物件上面去。又稱 Wrapper Pattern,在程式碼實現的時候,確實有“包裝”的意思。 類圖 圖:來自《Head First Design Patterns》 可以看出,裝飾者模式裡面,有4個角色:Comp

Java設計模式——裝飾模式

應用場景: 一個人身高175cm,他覺得太矮泡不到妹子,穿了一雙加厚的襪子增加1cm,嗯感覺效果不明顯,再踩在一雙加厚1cm的鞋墊,最後還不滿意,再穿了一雙內建增高3cm的鞋子,成功地把自己的身高“提高”到180cm+,他就被裝飾成“大長腿”了。 什麼是

C#設計模式-裝飾模式

一.裝飾者模式的定義: 裝飾模式是在不必改變原類檔案和使用繼承的情況下,動態地擴充套件一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。 結構: (1)抽象構件(Component)角色:給出一個抽象介面,以規範準備接收附加責任的物件。 (2)具體構件

(34)C#設計模式——裝飾模式Decorator Pattern

引言 在軟體開發中,我們經常想要對一類物件新增不同的功能,例如要給手機新增貼膜、掛件、外殼等。如果此時使用繼承來實現的話,我們就需要定義無數的類,這樣會導致“子類爆炸”的問題。為了解決這個問題,可以使用裝飾者模式來動態地給一個物件新增額外的職責。 裝飾者模式的詳細介紹

設計模式----裝飾模式decorator pattern

SchoolReport.java程式碼如下:package com.designPattern.decorator;public abstract class SchoolReport { public abstract void report(); public abst

給愛用繼承的人一個全新的設計眼界-----裝飾模式(java I/O的原始碼思想就是基於這個來的)

導讀:如果感覺有點困難,請看後面的例子和最後一句話 開始的思維: 這是一個父類,假設是某種產品的總稱,比如:飲料(beverage): public class Beverage { private String description;//產品的描述 pu

學習、探究Java設計模式——裝飾模式

定義 裝飾者模式:在不改變原類檔案以及不使用繼承的情況下,動態地將責任附加到物件上,從而實現動態拓展一個物件的功能。它是通過建立一個包裝物件,也就是裝飾來包裹真實的物件。 設計原則 要使用裝飾者模式,需要滿足以下設計原則: 1、多用組合,少用繼承

javascript設計模式——裝飾模式

應用 提交表單 不同 ora fin input 是否為空 插件 和數 前面的話   在程序開發中,許多時候都並不希望某個類天生就非常龐大,一次性包含許多職責。那麽可以使用裝飾者模式。裝飾者模式可以動態地給某個對象添加一些額外的職責,而不會影響從這個類中派生的其他對象。本

C# - 設計模式 - 裝飾模式

private 實現類 comm 回路 匯總 abs round C# 由於 裝飾者模式 問題場景 如果要計算一杯咖啡的價格,只需要調用其獲取價格的方法就可以了,但是如果需要加一些材料,比如牛奶、巧克力、糖等等,這些材料也必須返回它們價格以便於用於匯總計算,但是材料有很

設計模式——裝飾模式

什麽 很多 方法 info 改變 劃分 llb 設計 nts - 什麽是裝飾者模型 裝飾者模型通過組合的方式擴展對象的特性,動態地給對象添加額外的職責。在增加功能上,裝飾模式比生成子類更加靈活。 - 職責劃分 Component抽象構建,是接口或者抽象類,就是定義原始對象

C#設計模式——裝飾模式

方式 實例 oid spa als note 客戶 基本功 pan 一、裝飾者模式介紹: 裝飾者模式——以對客戶透明的方式動態地給一個對象添加額外的職責,采用對象組合而非繼承的方式實現了再運行時動態地擴展對象功能的能力,相比生成子類可以更靈活地增加功能,而且可以根據需要擴展

設計模式-裝飾模式(Go語言描述)

什麼是裝飾者模式 好久沒有更新設計模式系列的部落格了, 今天我們來聊一聊裝飾者模式, 用過java的同學肯定對裝飾者模式非常熟悉,就算你不知道什麼是裝飾者模式這概念, 你也一定在程式碼中經常用到這個模式,為什麼這麼說呢? 大家都用過java中的流吧, 我們可以這樣寫: new B

android設計模式——裝飾模式

定義:允許向一個現有的物件新增新的功能,同時又不改變其結構。 使用場景:能夠動態地擴充套件類的功能 應用舉例:一個畫可以被裝在畫框裡,並且被蒙上玻璃,這時候畫,玻璃,畫框組成了一個東西。 類圖: Comppoent: 抽象元件 ConcreteComponet:元件的具體