裝飾者模式:動態將責任附加到對象上。若要擴展功能,裝飾者提供了比集成更有彈性的替代方案。編程
原則:封裝變化;多用組合,少用繼承;針對接口編程,不針對實現編程;爲交互對象之間的鬆耦合設計而努力;對擴展開放,對修改關閉。ide
Beverage是抽象基類,是被裝飾者,getDescription()有基本實現,子類可重寫,cost()是抽象方法,子類必須重寫。HouseBlend,DarkRoast,Espresso,Decaf是具體的被裝飾者,只須要擴展實現基類中的cost()方法。CondimentDecorator是裝飾者抽象基類,繼承自Beverage,下面的四個是具體的裝飾者子類。擴展實現cost()和getDescription()方法,cost()須要將本身的花費加上。測試
Beverage抽象基類被裝飾者:this
1 public abstract class Beverage { 2 3 String description = "Unknown Beverage"; 4 5 public String getDescription() { 6 return description; 7 } 8 public abstract double cost(); 9 }
CondimentDecorator抽象基類裝飾者:spa
1 public abstract class CondimentDecorator extends Beverage{ 2 public abstract String getDescription(); 3 }
DarkRoast具體被裝飾者子類:設計
1 public class DarkRoast extends Beverage { 2 3 public DarkRoast() { 4 description = "DarkRoast"; 5 } 6 public double cost() { 7 return 0.99; 8 } 9 10 }
Mocha具體裝飾者子類:code
1 public class Mocha extends CondimentDecorator{ 2 Beverage beverage; 3 4 public Mocha(Beverage beverage) { 5 this.beverage = beverage; 6 } 7 public String getDescription() { 8 System.out.println("mochaDescription"); 9 return beverage.getDescription() + ",Mocha"; 10 } 11 public double cost() { 12 System.out.println("mochaCost"); 13 return 0.20 + beverage.cost(); 14 } 15 }
Whip具體裝飾者子類:對象
1 public class Whip extends CondimentDecorator{ 2 Beverage beverage; 3 4 public Whip(Beverage beverage) { 5 this.beverage = beverage; 6 } 7 public String getDescription() { 8 System.out.println("whipDescription"); 9 return beverage.getDescription() + ",Whip"; 10 } 11 public double cost() { 12 System.out.println("whipCost"); 13 return 0.10 + beverage.cost(); 14 } 15 }
測試類:blog
1 public class StarbuzzCoffee { 2 3 public static void main(String[] args) { 4 Beverage beverage = new Espresso(); 5 System.out.println(beverage.getDescription() + "$" + beverage.cost()); 6 Beverage beverage2 = new DarkRoast(); 7 beverage2 = new Mocha(beverage2); 8 beverage2 = new Mocha(beverage2); 9 beverage2 = new Whip(beverage2); 10 System.out.println(beverage2.getDescription() + "$" + beverage2.cost()); 11 } 12 13 }
1.裝飾者和被裝飾者對象具備相同的超類型,因此在任何使用被裝飾者對象的場合,能夠用裝飾過的對象來代替它。(因此裝飾者類反映出被裝飾的組件的類型)繼承
2.裝飾者不只能夠裝飾具體構件,還能夠裝飾裝飾者。
3.裝飾者和被裝飾者都繼承(或實現)自相同的超類型(Component),咱們是利用繼承達到「類型匹配」,而不是利用繼承得到「行爲」。當咱們將裝飾者與組件(或裝飾者)組合時,加入的新的行爲並非繼承自超類,而是由組合對象(ConcreteComponent或ConcreteDecorator)得來的。
4.雖然裝飾者模式能夠爲設計注入彈性,但裝飾者也經常形成設計中有大量的小對象,若是過分使用會讓程序變得很複雜。
5.裝飾模式VS繼承:裝飾模式是使用組合和委託用來擴展特定對象的功能,不須要子類,動態地在運行時給對象加上新的行爲,防止了因爲子類而致使的複雜和混亂,具備更多的靈活性。而繼承是用來擴展一類對象的功能,須要子類,靜態地在編譯時分派職責,致使了不少子類的產生,缺少靈活性。
6.裝飾者通常對組件的客戶是透明的,除非客戶程序依賴於組件的具體類型
7.Decorator裝飾者角色並非必須的,當你僅須要添加一個職責時,沒有必要定義抽象Decorator類。你經常須要處理現存的類層次結構而不是設計一個新系統,這時你能夠把Decorator向Component轉發請求的職責合併到Concrete Decorator中。
8.改變對象外殼與改變對象內核:咱們能夠將Decorator看做一個對象的外殼,它能夠改變這個對象的行爲。另一種方法是改變對象的內核。例如, Strategy(策略)模式就是一個用於改變內核的很好的模式。
I/O應用: