咱們都知道。可以使用兩種方式給一個類或者對象加入行爲。java
一是使用繼承。繼承是給一個類加入行爲的比較有效的途徑。經過使用繼承,可以使得子類在擁有自身方法的同一時候,還可以擁有父類的方法。但是使用繼承是靜態的,在編譯的時候就已經決定了子類的行爲,咱們不便於控制添加行爲的方式和時機。ide
二是使用關聯。組合即將一個對象嵌入到還有一個對象中,由還有一個對象來決定是否引用該對象來擴展本身的行爲。this
這是一種動態的方式,咱們可以在應用程序中動態的控制。spa
與繼承相比,關聯關係的優點就在於不會破壞類的封裝性,且具備較好的鬆耦合性,可以使系統更加easy維護。但是它的缺點就在於要建立比繼承不少其它的對象設計
1、裝飾者的定義:code
裝飾着模式動態的將責任附加到對象上,若想要擴展功能,裝飾着提供比繼承更有彈性的替代方案。對象
2、裝飾着模式的UML圖:繼承
Compoent類:抽象類,每個組件可以單獨使用它。或者包裝起來使用接口
ConcreteCompoent類:動態載入新行爲的對象。繼承於Compoentip
Decorator類:裝飾着共同實現的接口,可以使抽象類
ConcreteDecorator一、ConcreteDecorator2類:裝飾實例,裝飾者包着Compent
3、應用場景:
Startbuzz是以擴張速度最快的的咖啡連鎖店。因爲擴張太快。他們準備更新訂單系統。以供應需求。他們原先的設計是這種。
購買咖啡時,可以要求在當中增長各類調料。好比:牛奶(Milk)、豆漿(Soy)、摩卡(Mocha)。Startbuzz會依據不一樣的調料收取不一樣的費用,因此訂單必須考慮到調料部分。。
這是他們的第一次嘗試。。。
解決方式:
4、編寫代碼
Compotemt:Beverage類
//@file:beverage.java public abstract class Beverage { String description = "Unknown Beverage"; public String getDescription(){ return description; } public abstract double cost(); }
ConcreteCompotemt:Espresso類
//濃縮咖啡 //@file:Espresso.java public class Espresso extends Beverage { <span style="white-space:pre"> </span>public Espresso(){ description = "Espresso"; } @Override public double cost() { return 1; } }CondimentDecorator : HouseBlend 類
//@file:HouseBlend.java 、 //深烤烘焙 public class HouseBlend extends Beverage { public HouseBlend(){ description = "HouseBlend"; } @Override public double cost() { return 0.5; } }Decorator:CondimentDecorator類
//@file:CondimentDecorator.java public abstract class CondimentDecorator extends Beverage{ abstract public String getDescription(); }
ConcreteDecorator:Milk類
//file:Milk.java 牛奶味道的調料 public class Milk extends CondimentDecorator { Beverage beverage; public Milk(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription()+"-Milk"; } @Override public double cost() { return beverage.cost()+2.0; } }
ConcreteDecorator:Mocha類
//摩卡味道的調料 public class Mocha extends CondimentDecorator { Beverage beverage; public Mocha(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription()+"-Mocha"; } @Override public double cost() { return beverage.cost()+3.0; } }
ConcreteCDecorator:Soy類
//豆漿味道的調料 public class Soy extends CondimentDecorator { Beverage beverage; public Soy(Beverage beverage){ this.beverage = beverage; } @Override public String getDescription() { return beverage.getDescription()+"-Soy"; } @Override public double cost() { return beverage.cost()+4.0; } }
開始下單啦!!!
public class OrderApp { public static void main(String[] args) { Beverage beverage1 = new HouseBlend(); beverage1 = new Milk(beverage1); beverage1 = new Mocha(beverage1); beverage1 = new Soy(beverage1); System.out.println("beverage1 description:"+beverage1.getDescription()+"\ncost:"+beverage1.cost()); Beverage beverage2 = new Espresso(); beverage2= new Milk(beverage2); beverage2 = new Mocha(beverage2); System.out.println("beverage2 description:"+beverage2.getDescription()+"\ncost:"+beverage2.cost()); } }
output:
beverage1 description:HouseBlend-Milk-Mocha-Soy cost:9.5 beverage2 description:Espresso-Milk-Mocha cost:6.0