裝飾者模式:動態將責任附加到對象上,要拓展功能,提供了比繼承更有彈性的方案。
很多文章也是拿了書上的例子來講,同時寫到,有的調料裝飾者都必須實現 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的時候不清晰。但是可以通過對象之前的嵌入組合擴展出很多行爲,這也是裝飾者模式最大的優點。