給愛用繼承的人一個全新的設計眼界-----裝飾者模式(java I/O的原始碼思想就是基於這個來的)
阿新 • • 發佈:2019-01-29
導讀:如果感覺有點困難,請看後面的例子和最後一句話
開始的思維:
這是一個父類,假設是某種產品的總稱,比如:飲料(beverage):
public class Beverage {
private String description;//產品的描述
public String getDescription(){//返回產品的描述
return this.description;
}
public String cost(){ //由子類繼承來返回當前產品的價格
return "no chird";
}
}
如果有很多產品,那麼就需要建立很多的子類,導致維護的時候就會變得非常麻煩。(子類繼承cost() 只重寫方法,返回對應的價格。 )
設計原則:類應該對擴充套件開發,對修改關閉。
我們的目標是允許類容易擴充套件,在不修改現有的程式碼的情況下,就可以搭配新的行為,如能實現這樣的目標,有什麼好處呢?這樣的設計具有彈性可以應對改變,可以接受新的功能來應對改變的 需求。
正文開始:
要做到:
1.拿一個物件,比如DarkRoast(**咖啡)
2.以摩卡(Mocha)物件裝飾它
3.對奶泡(Whip)物件裝飾它
4.呼叫cost()方法,並依賴委託(delegate) 將調料的價格加上去
所謂裝飾者就是分為兩類,一類是裝飾的物件,另一類是被裝飾的物件。就像紅豆牛奶,紅豆是修飾者,牛奶是被修飾者,
在飲品店裡,你可以單買牛奶,但是不可以單買紅豆(配料)[不要鑽牛角尖,認真你就輸了.....] 所以我們在寫程式的時候就需要實現兩個型別的類。
那麼現在是被裝飾物件的主類,他是一個抽象物件(介面也可以,隨你開心)
public abstract class Beverage {
String description = "Unknown Beverage";
public String getDescription() {
return this.description;
}
public abstract Double cost();
}
它是所有的超類,主要的作用是把後面的子類的形態定住。
接下來是裝飾者的抽象類
//首先,必須讓Condiment Decorator 能夠取代Beverage,所以將CondimentDecorator擴充套件自Beverage類 public abstract class CondimentDecorator extends Beverage { public abstract String getDescription();//所有的被裝飾者都必須重新實現getDescription()方法。 }
讓其作為上面超類的子類,也是為了把形態固定住,重新命名肯定是必須的。
接下來是實現多個裝飾物件
//摩卡(配料)
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 .20 + beverage.cost(); //組合價格
}
}
public class Whip extends CondimentDecorator{
Beverage beverage;
//把飲料(主體傳入)
public Whip(Beverage beverage) {
this.beverage = beverage;
}
@Override
public String getDescription() {
return beverage.getDescription() + ", Whip";
}
@Override
public Double cost() {
return .30 + beverage.cost(); //組合價格
}
}
接下來是被裝飾者
//濃縮咖啡
public class Espresso extends Beverage{
public Espresso(){
description = "Espresso";
}
@Override
public Double cost() {
return 1.99;
}
}
//另一種
public class HouseBlend extends Beverage {
public HouseBlend() {
description = "House Blend";
}
@Override
public Double cost() {
return .89;
}
}
接下來是測試類:
public class StarbuzzCoffee {
public static void main(String args[]) {
Beverage beverage = new Espresso();
//訂一杯Espresso 不加調理 列印價格
System.out.println(beverage.getDescription()
+ " $" + beverage.cost());
Beverage beverage1 = new HouseBlend();
beverage1 = new Mocha(beverage1);
beverage1 = new Mocha(beverage1);//加入第二份
beverage1 = new Whip(beverage1);
System.out.println(beverage1.getDescription()
+ " $" + beverage1.cost());
}
}