每天一個設計模式 -9 裝飾者模式 一、現實 使用繼承不總能夠實現最有彈性和最好維護的設計。 利用組合和委托可以在運行時具有繼承行為的效果。 利用繼承設計子類的行為,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行為。 利用組合的做法擴展對象的行為,就可以在運行時動態地進行擴展。 二、認識裝飾 ...
每天一個設計模式 -9 裝飾者模式
一、現實
- 使用繼承不總能夠實現最有彈性和最好維護的設計。
- 利用組合和委托可以在運行時具有繼承行為的效果。
利用繼承設計子類的行為,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行為。
利用組合的做法擴展對象的行為,就可以在運行時動態地進行擴展。
二、認識裝飾者模式
角色:
- 裝飾者
- 組件
舉例:
給咖啡添加調料(咖啡(組件或被裝飾對象),調料(裝飾者)種類很多。咖啡,調料需要付費)並能算出需要付款的總費用,用圖形表示:
- 裝飾者和被裝飾對象有相同的超類型。
- 可以用一個或多個裝飾者包裝一個對象。
- 裝飾者和被裝飾對象有相同的超類型,所以在任何需要原始對象(被包裝的)的場合,可以用裝飾過的對象代替它。
- 裝飾者可以在所委托被裝飾者的行為之前與/或之後,加上自己的行為,已達到特定的目的。
- 對象可以在任何時候被裝飾,所以可以在運行是動態地,不限量的用你喜歡的裝飾者來裝飾對象。
三、定義裝飾者模式
定義:裝飾者模式動態的將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案
通用的類圖:
對這個類圖進行改造,完成上面的例子:
四、源代碼
抽象類 Coffee:一個description欄位,一個抽象方法cost,一個有預設實現的getDescription()方法
public abstract class Coffee { String description = "未知的咖啡"; public Coffee(){ } public void finalize() throws Throwable { } public abstract double cost(); public String getDescription(){ return description; } }Coffee
四個具體的Coffee類Coffee1,Coffee2...,繼承自Coffee,實現抽象方法cost()
public class Coffee1 extends Coffee { public Coffee1(){ description = "咖啡1"; } public void finalize() throws Throwable { super.finalize(); } public double cost(){ return 10; } } public class Coffee2 extends Coffee { public Coffee2(){ description = "咖啡2"; } public void finalize() throws Throwable { super.finalize(); } public double cost(){ return 20; } } public class Coffee3 extends Coffee { public Coffee3(){ description = "咖啡3"; } public void finalize() throws Throwable { super.finalize(); } public double cost(){ return 30; } } public class Coffee4 extends Coffee { public Coffee4(){ description = "咖啡4"; } public void finalize() throws Throwable { super.finalize(); } public double cost(){ return 20; } }Coffee的具體類
抽象類 CondimentDectorator:繼承自Coffee 一個抽象方法getDescription(),強制子類重寫
public abstract class CondimentDecorator extends Coffee { public Coffee m_Coffee; public CondimentDecorator(){ } public void finalize() throws Throwable { super.finalize(); } public abstract String getDescription(); }CondimentDectorator
三個具體的CondimentDectorator,Condiment1...,繼承自CondimentDectorator,實現抽象方法getDescription()
public class Condiment1 extends CondimentDecorator { public Condiment1(Coffee coffee){ m_Coffee = coffee; } public void finalize() throws Throwable { super.finalize(); } public double cost(){ //計算自己和被裝飾的對象的價格 return m_Coffee.cost()+0.9; } public String getDescription(){ return m_Coffee.getDescription()+",Condiment1"; } } //---------------------------------------------------------------------------- public class Condiment2 extends CondimentDecorator { public Condiment2(Coffee coffee){ m_Coffee = coffee; } public void finalize() throws Throwable { super.finalize(); } public double cost(){ return m_Coffee.cost()+0.7; } public String getDescription(){ return m_Coffee.getDescription()+",Condiment2"; } } //--------------------------------------------------------------------------- public class Condiment3 extends CondimentDecorator { public Condiment3(Coffee coffee){ m_Coffee = coffee; } public void finalize() throws Throwable { super.finalize(); } public double cost(){ return m_Coffee.cost()+0.5; } public String getDescription(){ return m_Coffee.getDescription()+",Condiment3"; } }CondimentDectorator具體類
五、總結
從這次學習中能看出一些OO原則:
- 封裝變化(Coffee封裝了變化)
- 多用組合,少用繼承(繼承可能會變得死板,組合達到擴展則很靈活)
- 針對藉口編程,不針對實現編程(抽象類)
- 對擴展開放,對修改關閉
- 依賴抽象
轉載註明出處:http://www.cnblogs.com/xiemubg/p/6753811.html