裝飾者模式 Decorator
什么是裝飾者模式:動態將職責附加到對象上,若要擴展功能,裝飾者提供了比繼承更具彈性的代替方案。
適用性:當采用類繼承的方式會造成類爆炸的情況。如本文的例子中,基本飲料(被裝飾者)可能有茶、水、牛奶等等、可以添加的(裝飾者)有糖、果肉、珍珠等。
如果通過繼承的方式,為每一種類型的奶茶設計一種類會造成類爆炸,同時也不利於后期的擴展(如又添加一種基本飲料豆漿的情況),此時通過裝飾者模式可以很好的解決問題。
裝飾者模式本質是一種組合的思想(不同於繼承的思想),多組合少繼承。利用繼承設計子類的行為,是在編譯時靜態決定的,而且所有的子類都會繼承到相同的行為。然而,如果能夠利用組合的做法擴展對象的行為,就可以在運行時動態地進行擴展。
裝飾者模式的主要組成部分:抽象被裝飾者、具體被裝飾者、抽象裝飾者、具體裝飾者。(當只有一個具體被裝飾者、一個具體裝飾者,其對應的抽象類可以省略)。
裝飾者模式類圖:
裝飾者模式要點:
1 多種具體被裝飾者(主體類)抽象出一個抽象被裝飾類,后面通過多態,動態傳遞具體對象。
2 抽象裝飾類繼承抽象被裝飾者(保持接口);要求傳入被裝飾者(使用父類應用、protected修飾);
3 多種具體裝飾者抽象出一個抽象裝飾類。
4 具體裝飾者中,可以添加新方法,可以重寫方法;需要使用被裝飾者方法的地方用傳入的被裝飾者引用。
裝飾者模式的基本代碼:
/** * 被裝飾抽象類——基本飲料 * * 作用:當具體的被裝飾類有多種時,抽象提出該抽象類,用於后面實現多態。 */ public abstract class BaseDrink { public abstract int calculate(); public abstract void display(); }
/** * 具體的被裝飾者類—— Water類 * 繼承抽象的被裝飾者類,並實現其中的抽象方法。 */ public class Water extends BaseDrink{ @Override public int calculate() { return 3; } @Override public void display() { System.out.println("water"); } }
/** * 具體的被裝飾者類—— Tea類 * 繼承抽象的被裝飾者類,並實現其中的抽象方法。 */ public class Tea extends BaseDrink{ @Override public int calculate() { return 5; } @Override public void display() { System.out.println("Tea"); } }
/** * 抽象裝飾者類——Decorator * 要點:1.抽象裝飾者類中繼承該抽象類以保持接口規范 * 2.包含該抽象類的引用以通過多態的方式對多種被裝飾者類進行裝飾。 */ public abstract class Decorator extends BaseDrink{ //繼承,保持接口 protected BaseDrink bd; //引用,多態 public Decorator(BaseDrink bd) { this.bd = bd; } @Override public int calculate() { return bd.calculate(); } @Override public void display() { bd.display(); } }
/** * 裝飾者類 果肉 */ public class FleshDecorator extends Decorator{ public FleshDecorator(BaseDrink bd) { super(bd); } @Override public int calculate() { return super.calculate() + 2; } @Override public void display() { super.display(); System.out.println("+ flesh"); } }
/**
* 裝飾者類 糖
*/
public class SugarDecorator extends Decorator{
public SugarDecorator(BaseDrink bd) {
super(bd);
}
@Override
public int calculate() {
return super.calculate()+1;
}
@Override
public void display() {
bd.display();
System.out.println("+ sugar");
}
public void addMoreSugar(){
System.out.println("add more sugar");
}
}
/** * 測試用例 */ public class TestCase { public static void main(String[] args) { BaseDrink water = new Water(); SugarDecorator sugarWater = new SugarDecorator(water); sugarWater.addMoreSugar(); sugarWater.display(); System.out.println(sugarWater.calculate()); System.out.println("========================="); BaseDrink tea = new Tea(); FleshDecorator fleshTea = new FleshDecorator(tea); fleshTea.display(); System.out.println(fleshTea.calculate()); } }
//結果 F:\deaIC-2019.1.3-jbr11.win\jre64\bin\java.exe -javaagent:F:\deaIC-2019.1.3-jbr11.win\lib\idea_rt.jar=7425:F:\deaIC-2019.1.3-jbr11.win\bin -Dfile.encoding=UTF-8 -classpath E:\eclipse-workspace\decoratorDemo\out\production\decoratorDemo TestCase add more sugar water + sugar 4 ========================= Tea + flesh 7