1. 程式人生 > >給愛用繼承的人一個全新的設計眼界-----裝飾者模式(java I/O的原始碼思想就是基於這個來的)

給愛用繼承的人一個全新的設計眼界-----裝飾者模式(java I/O的原始碼思想就是基於這個來的)

導讀:如果感覺有點困難,請看後面的例子和最後一句話

開始的思維:

這是一個父類,假設是某種產品的總稱,比如:飲料(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());
    }
}

很顯然,被裝飾者類並不需要做太多的事,而裝飾者類則需要在被裝飾者的基礎上增加加上自己後對應的變化操作,所有裝飾者模式就是利用多重組合來實現的。