首先讓我們看一下裝飾者模式(我愛叫他套娃模式)的概念:動態(tài)的將責任附加到對象上,若要擴展功能,裝飾者提供了比繼承者更有彈性的集成方案。什么?沒看懂?沒關系,最后再來看這個概念,想讓讓我們來看一個咖啡屋項目(就是點各式 各樣的咖啡)。 原本的設計如下:
看似很好的設計,但是別忘了,買咖啡時候我們會讓他們給我們加一系列的調料,例如蒸奶、 摩卡......。所以,在這時咖啡店的設計就變成了,如下:
不錯,你看到了類爆炸! 好啦,現(xiàn)在有對這個系統(tǒng)做出了改進,如下:
好啦,現(xiàn)在這個設計相比之前的的確好了許多,但是如果我們要修改配料呢?那么就必須修改 超類,這時候就違反了一條設計原則:類應該對擴展開放,對修改關閉! 所以這個時候,裝飾者模式單誕生了?。。。?! 來看個例子: 如果顧客現(xiàn)在要一杯摩卡和奶泡深培咖啡。那么,要做的是: ①拿一個深培咖啡(DarkRoast)對象 ②以摩卡(Mocha)對象裝飾它 ③以奶泡(Whip)裝飾它 ④調用cost()方法,并依賴委托(delegate)將調料的幾千加上去 如何工作? ①以DarkRoast對象開始
②顧客想要摩卡(Mocha),所以建立一個Mocha對象,并用它將DarkRoast對象包起來 ③顧客也想要奶泡(Whip),所以建立一個Whip裝飾者,并用它將Mocha對象包起來。別 忘了,DarkRoast繼承自Beverage,且有一個cost()方法,用來計算飲料價錢 ④現(xiàn)在,該是為顧客算錢的時候了。通過調用最外圈的裝飾者的cost就可以辦到,如下圖: 好了,請記住裝飾者和被裝飾對象有相同的超類型!現(xiàn)在讓我們寫一些代碼,了解他的工作吧: 首先看一下我們現(xiàn)在的設計圖: 先從Beverage類下手,這不需要改變原始設計。如下圖:
1 public abstract class Beverage { 2 String description = "Unknown Beverage"; 3 4 public String getDescription(){ 5 return description; 6 } 7 8 public abstract double cost(); 9 }
Beverage很簡單。讓我們來實現(xiàn)Condiment(調料)抽象類,也就是裝飾這類吧: 1 public abstract class CondimentDecorator extends Beverage{ 2 Beverage beverage; 3 4 public abstract String getDescription(); 5 } 現(xiàn)在,該是實現(xiàn)一些飲料的時候了!先從濃縮咖啡(Espresso)開始: Espresso.java: 1 public class Espresso extends Beverage { 2 public Espresso() { 3 description = "Espresso"; 4 } 5 6 public double cost() { 7 return 1.99; 8 } 9 } DarkRoast.java: 1 public class DarkRoast extends Beverage { 2 public DarkRoast() { 3 description = "Dark Roast Coffee"; 4 } 5 6 public double cost() { 7 return .99; 8 } 9 } HouseBlend.java: 1 public class HouseBlend extends Beverage { 2 public HouseBlend() { 3 description = "House Blend Coffee"; 4 } 5 6 public double cost() { 7 return .89; 8 } 9 }
開始協(xié)調料代碼: Mocha.java: 1 public class Mocha extends CondimentDecorator { 2 public Mocha(Beverage beverage) { 3 this.beverage = beverage; 4 } 5 6 public String getDescription() { 7 return beverage.getDescription() + ", Mocha"; 8 } 9 10 public double cost() { 11 return .20 + beverage.cost(); 12 } 13 } Milk.java: 1 public class Milk extends CondimentDecorator { 2 public Milk(Beverage beverage) { 3 this.beverage = beverage; 4 } 5 6 public String getDescription() { 7 return beverage.getDescription() + ", Milk"; 8 } 9 10 public double cost() { 11 return .10 + beverage.cost(); 12 } 13 } Soy.java: 1 public class Soy extends CondimentDecorator { 2 public Soy(Beverage beverage) { 3 this.beverage = beverage; 4 } 5 6 public String getDescription() { 7 return beverage.getDescription() + ", Soy"; 8 } 9 10 public double cost() { 11 return .15 + beverage.cost(); 12 } 13 } Whip.java: 1 public class Whip extends CondimentDecorator { 2 public Whip(Beverage beverage) { 3 this.beverage = beverage; 4 } 5 6 public String getDescription() { 7 return beverage.getDescription() + ", Whip"; 8 } 9 10 public double cost() { 11 return .10 + beverage.cost(); 12 } 13 } 測試代碼: Main.java: 1 public class Main { 2 3 public static void main(String[] args) { 4 Beverage beverage = new Espresso(); 5 System.out.println(beverage.getDescription() 6 + " $" + beverage.cost()); 7 8 Beverage beverage2 = new DarkRoast(); 9 beverage2 = new Mocha(beverage2); 10 beverage2 = new Mocha(beverage2); 11 beverage2 = new Whip(beverage2); 12 System.out.println(beverage2.getDescription() 13 + " $" + beverage2.cost()); 14 15 Beverage beverage3 = new HouseBlend(); 16 beverage3 = new Soy(beverage3); 17 beverage3 = new Mocha(beverage3); 18 beverage3 = new Whip(beverage3); 19 System.out.println(beverage3.getDescription() 20 + " $" + beverage3.cost()); 21 } 22 } 結果:
|
|