設計模式之(三)——裝飾者模式,爲什麼裝飾者對象不直接繼承父類對象

 

 

裝飾者模式:動態將責任附加到對象上,要拓展功能,提供了比繼承更有彈性的方案。

很多文章也是拿了書上的例子來講,同時寫到,有的調料裝飾者都必須實現 getDescription() 大家可以先考慮下,稍後我們會說。最後都是沒說,還有思考的同時你也應該會拋出一些問題,這樣能讓你對該模式的印象更加的深刻。

 

/**
 * 飲料
 */
public abstract class Beverage {
     public String description = "unknown";
     public String getDescription(){
            return description;
     }
     public abstract double cost();
}
/**
 *  裝飾者
 */
public abstract class Condiment extends Beverage{

     @Override
     public abstract String getDescription();
}
/**
 * 濃咖啡,被裝飾者
 */
public class Latte extends Beverage{

     @Override
     public String getDescription() {
            return "Latte";
     }

     @Override
     public double cost() {
            return 1.0;
     }

}
/**
 * 具體的裝飾者
 */
public class Milk extends Condiment {
     public Beverage beverage;
     public double milkcost = 0.5;
     public Milk(Beverage beverage){
            this. beverage = beverage;
     }
     
     @Override
     public String getDescription () {
            return "milk add:"+ beverage.getDescription();
     }

     @Override
     public double cost () {
            return milkcost+ beverage.cost();
     }

}
/**
 * 具體裝飾者
 */
public class Whip extends Beverage {
    public Beverage beverage;
    public double whipcost = 0.2;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }

    @Override
    public String getDescription() {
        return "whip add:" + beverage.getDescription();
    }

    @Override
    public double cost () {
    return whipcost+ beverage.cost();
}
public class TestA {
     public static void main(String[] args) {
           Beverage b = new Espresso();
            Condiment c = new Milk(b);
           System. out.println(c.getDescription());
           System. out.println(c.cost());
     }
}

 

public class TestB {
     public static void main(String[] args) {
           Beverage b = new Espresso();
           System. out.println(b.cost()+ " "+b.getDescription());
           Beverage c = new Milk(b); //第一個裝飾,把裝飾者當成了構造器參數
           c = new Milk(c);//第二個裝飾
           c = new Whip(c);//第三個裝飾
           System. out.println(c.cost()+ " "+c.getDescription());
     }
}

 

TestA只是很簡單的一層裝飾,TestB纔是裝飾者的核心所在。

這樣能一層嵌一層。這纔是核心。但是沒搞懂,爲什麼裝飾器,實現的是Condiment。

而Condiment本身就是繼承Beverage。我的Milk和Whip直接繼承Beverage也是可以的。

 

爲什麼裝飾者都去先繼承了Decorator,問過有經驗的人,給了我很生動的比喻,具體的裝飾者就是稀飯,炒飯,乾飯,中間層是飯。再結合自己所思考的,如果飯繼承是食物,那麼你用稀飯直接去繼承食物也是沒問題的。中間層是給了一層清晰的分類。專門用來區分裝飾者。你看Milk和Whip的繼承就明顯看出這兩者是裝飾者。所以中間層的目的在此,是對所有裝飾者集合的一層抽象,暫時想到的是這些。

由IO流的使用你就可以發現模式的缺點,裝飾者的設計會導致有很多很多類,使用api的時候不清晰。但是可以通過對象之前的嵌入組合擴展出很多行爲,這也是裝飾者模式最大的優點。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章