裝飾者模式說明:動態地將責任加於物件上,若要擴充功能,裝飾者提供了比繼承更有彈性的選擇。

  • 裝飾者和被裝飾者有相同的超型態
  • 你可以利用一個或多個裝飾者包裝一個物件
  • 所以我們可以在任何需要傳遞原始的(被包裝的)物件場合,改以傳遞裝飾後的(包裝的)物件。
  • 裝飾者可以在所委派被裝飾者的行為,之前或(與)之後加上自己的行為,達到目的。
  • 物件可在任何時候被裝飾,所以可以在執行期動態地用任何適合的裝飾者,來裝飾物件。

結構介紹

Component 主要物件 (擁有主要的功能及行為)
ComponentIABC 主要物件實作
DecorateComponent 裝飾者物件 ( 幫助補充或增加主體的功能及行為。)
DecorateComponentABC 裝飾者物件實作

讓星巴茲咖啡也符合這框架吧

主類別

public abstract class Beverage {  //飲料

    String description = "是什麼飲料呢";

    public String getDescrption(){
        return description;
    }
}
public abstract class CondimentDecorator extends Beverage{  //實踐一個裝飾者類別

    protected abstract String getDescription();

}

實踐飲料吧(次類別)

public class Espresso extends Beverage{  //濃咖啡

    public Espresso() {
        description = "Espresso";
    }
    public double cost() {
        return 1.99;
    } 

}

public class HouseBlend extends Beverage{  //綜合咖啡(?)

    public HouseBlend() {
        description = "House Blend Coffee";
    }
    public double cost() {
        return .89;
    } 

}

public class DarkRoast extends Beverage{ ... //黑咖啡

public class Decaf extends Beverage{ ... //低咖啡因

寫個各種配料 (裝飾者)

public class Mocha extends CondimentDecorator{  //摩卡
    Beverage beverage;                          //用一個實體變數紀錄Beverage物件,也就是被裝飾者
    public Mocha(Beverage beverage) {
        this.beverage = beverage;
    }
    public String getDescription() {            //讓被裝飾者(飲料)被記錄到實體變數中
        return beverage.getDescription() + ", Mocha"; 
    }
    public double cost() {
        return .20 + beverage.cost();
    } 

}

public class Soy extends CondimentDecorator{  //豆漿
    Beverage beverage;

    public Soy(Beverage beverage) {
        this.beverage = beverage;
    }
    public String getDescription() {
        return beverage.getDescription() + ", Soy";
    }
    public double cost() {
        return .10 + beverage.cost();
    } 

}

public class Whip extends CondimentDecorator{  //奶泡
    Beverage beverage;

    public Whip(Beverage beverage) {
        this.beverage = beverage;
    }
    public String getDescription() {
        return beverage.getDescription() + ", Whip";
    }
    public double cost() {
        return .20 + beverage.cost();
    } 

}

...想喝什麼配料自己加囉

實作囉

public class Starbox{  
    public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription()+"$"+beverage.cost()); //輸出
        //輸出: Espresso $1.99

        Beverage beverage2 = new DarkRoast(); //黑咖啡物件
        beverage2 = new Mocha(beverage2);//用摩卡裝飾
        beverage2 = new Mocha(beverage2);//雙重摩卡
        beverage2 = new Whip(beverage2);//用奶泡裝飾
        System.out.println(beverage2.getDescription()+"$"+beverage2.cost());
        //輸出: Dark Roast Coffe, Mocha, Mocha, Whip $1.49

        Beverage beverage3 = new HouseBlend(); //混和咖啡物件
        beverage2 = new Soy(beverage3);//用豆漿裝飾
        beverage2 = new Mocha(beverage3);//用摩卡裝飾
        beverage2 = new Whip(beverage3);//用奶泡裝飾
        System.out.println(beverage2.beverage3()+"$"+beverage3.cost());
        //輸出: House Blend Coffe, Soy, Mocha, Whip $1.34


    }

}

如果可以點中杯、大杯、特大杯,且分別為不同價錢?

public class Soy extends CondimentDecorator{  //豆漿
    Beverage beverage;

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

    public int getSize() {
        return beverage.getSize();
    }


    public String getDescription() {
        return beverage.getDescription() + ", Soy";
    }
    public double cost() {
        double cost = beverage.cost();
        if(getSize()==Beverage.TALL){
            cost +=.10;
        }else if(getSize()==Beverage.GRANDE){
            cost +=.15;
        }else if(getSize()==Beverage.VENTI){
            cost +=.15;
        }
        return cost;
    } 

}

results matching ""

    No results matching ""