在查看ContextWrapper源碼時,發現以下用法:
這種寫法叫裝飾者模式,相比於單純的實現接口,它具備更大的靈活性。
// 抽象類接口,規範餅的屬性
public interface ICake {
public String name(); // 名稱
public Double money(); // 價格
}
// 原味手抓餅類
public class PlainCake implements ICake {
@Override
public String name() {
return "原味手抓餅";
}
@Override
public Double money() {
return 3.5;
}
}
// 裝飾者(Decorator)
// 建立和原味餅的連接,得到原始餅屬性的同時,又不改動原對象。
public abstract class Deractor implements ICake {
ICake iCake;
public Deractor(ICake iCake) {
this.iCake = iCake;
}
@Override
public String name() {
return iCake.name();
}
@Override
public Double money(){
return iCake.money();
}
}
// 雞蛋手抓餅
public class EggCake extends Deractor {
public EggCake(ICake cake) {
super(cake);
}
@Override
public String name() {
return "雞蛋" + cake.name(); // 重寫父類方法,重新自定義屬性
}
@Override
public Double money() {
return 3.5 + 1.5; // 重寫父類方法,重新自定義屬性
}
}
// 牛肉味手抓餅
public class BeffCake extends Deractor {
public BeffCake(ICake cake) {
super(cake);
}
@Override
public String name() {
return "牛肉" + cake.name(); // 重寫父類方法,重新自定義屬性,下同
}
@Override
public Double money() {
return cake.money() + 3.0; // 重寫父類方法,重新自定義屬性,下同
}
}
測試類
public class Test {
public static void main(String[] args) {
//原味手抓餅類
plaincake plain = new plaincake();
System.out.println(sh.name() + " 價格: " + plain.money());
//雞蛋類,附加雞蛋屬性到手抓餅上
EggCake egg = new EggCake(plain);
System.out.println(egg.name() + " 價格:" + egg.money());
//牛肉類,附加牛肉屬性到手抓餅上
BeffCake beff = new BeffCake(egg);
System.out.println(beff.name() + " 價格:" + beff.money());
}
}
輸出的結果:
原味手抓餅 價格: 3.5
雞蛋原味手抓餅 價格:5.0
牛肉雞蛋原味手抓餅 價格:8.0
可以看到:
手抓餅在原來屬性沒有被改動的情況下,我們根據Decrator 抽象類,可以隨意擴展創建不同口味、價格的餅。