動態的給一個對象添加一些額外的職責,就增長功能來講,裝飾者模式比子類更加靈活java
星巴茲咖啡訂單系統,購買咖啡時根據顧客不一樣的咖啡類型,好比深度烘培或者混合咖啡和不一樣的原料好比摩卡,豆漿等原料計算咖啡的價格。按照正常思路設計首先有一個飲料的父類,提供cost計算價格的方法,其餘不一樣的原料不一樣類型的咖啡都繼承這個父類,這樣設計出來的子類會隨着原料的不停增長變的龐大無比。因此能夠經過裝飾者模式不一樣類型的咖啡用不一樣的原料進行裝飾,好比摩卡的混合咖啡,使用摩卡對象去裝飾混合咖啡對象,這樣會有極大的靈活性。ide
/** * 飲料類 * * @author Colin * @create 2018-03-20 **/ public abstract class Beverage { String description="Unknown Beverage"; public String getDescription(){ return description; } public abstract double cost(); } /** * 混合攪拌咖啡 * * @author Colin * @create 2018-03-20 **/ public class HouseBlend extends Beverage { public HouseBlend(){ this.description="混合咖啡"; } @Override public double cost() { return 1.5; } }
/** * 調料裝飾者類 * * @author Colin * @create 2018-03-20 **/ public abstract class CondimentDecorator extends Beverage { @Override public abstract String getDescription(); } /** * 摩卡 * * @author Colin * @create 2018-03-20 **/ public class Mocha extends CondimentDecorator { private Beverage beverage; public Mocha(Beverage beverage){ this.beverage=beverage; } @Override public String getDescription() { return beverage.getDescription()+",摩卡"; } @Override public double cost() { return 0.2+beverage.cost(); } } /** * 裝飾者測試類 * * @author Colin * @create 2018-03-20 **/ public class DecoratorTest { @Test public void testDecoraor(){ Beverage espressso=new Espressso(); espressso=new Mocha(espressso); espressso=new Whip(espressso); System.out.println("咖啡:"+espressso.getDescription()+",價格:"+espressso.cost()); } }
裝飾者模式應用場景:當系統須要新的功能的時候,是向舊的類中添加新的代碼,這些新加的代碼一般裝飾了原有類的核心職責或行爲,若是在主類中增長新的字段,新的方法,新的邏輯從而增長了主類的複雜度,而這些新加的東西僅僅是爲了知足一些只在特定狀況下才會執行的特殊行爲的須要,而裝飾者模式提供了很是好的解決方案,它把每一個要裝飾的功能放在單獨的類中,並讓這個類包裝它須要裝飾的對象,所以,當須要執行特殊行爲時,客戶代碼就能夠在運行時根據須要有選擇的按順序的使用裝飾功能包裝對象。有效的把類的核心功能和裝飾功能區分開了,並且能夠去除相關類中的重複的裝飾邏輯。測試
涉及的原則this
開閉原則:類應該對擴展開放,對修改關閉設計