裝飾者模式:動態地將責任附加到對象上。若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。java
特色:this
舉個栗子:設計
領導給你分配設計一個咖啡收款系統。咖啡能夠加配料,不一樣的配料收費不一樣。怎麼設計一個靈活的系統呢?思考三秒鐘3d
若是一個顧客想要摩卡(Mocha)和奶泡(Whip)深焙咖啡(DarkRoast),使用裝飾者模式怎麼作呢?code
一、以DarkRoast對象開始對象
二、顧客想要摩卡(Mocha),因此創建一個Mocha對象,並用它將DarkRoast對象包(wrap)起來。blog
三、顧客也想要奶泡(Whip),因此須要創建一個Whip裝飾者,並用它將Mocha對象包起來。別忘了,DarkRoast繼承自Beverage,且有一個cost()方法,用來計算飲料價錢。繼承
四、如今,該是爲顧客算錢的時候了。經過調用最外圈裝飾者(Whip)的cost()就能夠辦獲得。Whip的cost()會先委託它裝飾的對象(也就是Mocha)計算出價錢,而後再加上奶泡的價錢。ip
代碼實現:get
咖啡抽象類:
public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription() { return description; } public abstract double cost(); }
配料抽象類,繼承咖啡抽象類:
public abstract class CondimentDecorator extends Beverage { public abstract String getDescription(); }
咖啡的實現:
// 濃咖啡 public class Espresso extends Beverage { public Espresso() { description = "Espresso"; } public double cost() { return 1.99; } } // 深焙咖啡 public class DarkRoas extends Beverage { public DarkRoas () { description = "Dark Roas Coffee"; } public double cost() { return 0.89; } }
配料實現:
public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage) { this.beverage = beverage; } public String getDescription() { return beverage.getDescription() + ", Mocha"; } public double cost() { return 0.20 + beverage.cost(); } }
來一杯咖啡:
public class StarbuzzCoffee { public static void main(String args[]) { // 一杯不加配料的濃咖啡 Beverage beverage = new Espresso(); System.out.println(beverage.getDescription() + ": $" + beverage.cost()); // 雙倍摩卡和奶泡深焙咖啡 Beverage beverage2 = new DarkRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Whip(beverage2); System.out.println(beverage2.getDescription() + ": $" + beverage2.cost()); // 再來一杯調料爲豆漿、摩卡、奶泡的HouseBlend咖啡 Beverage beverage3 = new HouseBlend(); beverage3 = new Soy(beverage3); beverage3 = new Mocha(beverage3); beverage3 = new Whip(beverage3); System.out.println(beverage3.getDescription() + ": $" + beverage3.cost()); } }