02.裝飾者模式

02.裝飾者模式

1、認(rèn)識(shí)裝飾者模式

購(gòu)買(mǎi)咖啡時(shí),除了咖啡的各種口味以外,還可以加入各種調(diào)料,例如:蒸奶、豆?jié){、摩卡或奶蓋,星巴克會(huì)根據(jù)加入不同的調(diào)料收取不同的費(fèi)用,當(dāng)然還有大中小杯等等。

如果我們使用類(lèi)繼承的方式,會(huì)導(dǎo)致類(lèi)數(shù)目爆炸、設(shè)計(jì)死板,以及基類(lèi)加入的新功能并不適用于所有的子類(lèi)。

所以我們要采取不一樣的做法,我們以飲料為主體,然后采用調(diào)料類(lèi)、體積類(lèi)來(lái)修飾。

(1)拿一個(gè)深焙咖啡(DarkRoast)對(duì)象

(2)以摩卡(Mocha)對(duì)象來(lái)修飾

(3)以奶泡(Whip)來(lái)修飾

(4)以中杯(Medium)來(lái)修飾

(5)調(diào)用cost()方法,并依賴(lài)委托(delegate)將調(diào)料的價(jià)錢(qián)加上

2、定義

裝飾者模式:動(dòng)態(tài)地將責(zé)任附加到對(duì)象上,若要拓展功能,裝飾者提供了比繼承更有彈性的替代方案。

BD65E96F-442F-4A17-8CAD-429B18D95F1D_1_105_c.jpeg

3、設(shè)計(jì)原則:

開(kāi)放-關(guān)閉原則

類(lèi)應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。

我們的目標(biāo)是允許類(lèi)容易拓展,在不修改現(xiàn)有代碼的情況下,就可搭配新的行為。

4、設(shè)計(jì)

5DC568F8-7135-4D6B-B40D-D48673A49C73_1_201_a.jpeg

代碼實(shí)現(xiàn):

(1)裝飾者總抽象類(lèi)

public abstract class Beverage {
    public String description = "Unknown Beverage";

    public String getDescription(){
        return description;
    }
    public abstract double cost();
}

(2)調(diào)料裝飾者 抽象類(lèi)

public abstract class CondimentDecorator extends Beverage {
    @Override
    public abstract String getDescription();
}

(3)容量裝飾者 抽象類(lèi)

public abstract class Capacity extends Beverage {
    @Override
    public abstract String getDescription();
}

(4)四種咖啡實(shí)現(xiàn)類(lèi)

/**
 * 深度烘焙咖啡類(lèi)
 */
public class DarkRoast extends Beverage {

    public DarkRoast(){
        this.description = "DarkRoast";
    }

    @Override
    public double cost() {
        return 2.99;
    }
}
/**
 * 貓屎咖啡
 */

public class Decat extends Beverage {

    public Decat(){
        this.description = "Decat";
    }

    @Override
    public double cost() {
        return 1.89;
    }
}
/**
 * 濃縮咖啡類(lèi)
 */
public class Espresso extends Beverage {

    public Espresso(){
        this.description = "Espresso";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}
/**
 * 首選咖啡(星巴克咖啡名)
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "HouseBlend";
    }

    @Override
    public double cost() {
        return 0.89;
    }
}

(5)調(diào)料類(lèi)

/**
 * 摩卡  調(diào)料類(lèi)
 */
public class Mocha extends CondimentDecorator {
    private 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();
    }
}
/**
 * 大豆  調(diào)料類(lèi)
 */
public class Soy extends CondimentDecorator {
    private Beverage beverage;

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

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Soy";
    }

    @Override
    public double cost() {
        return .30 + beverage.cost();
    }
}
/**
 * 鮮奶  調(diào)料類(lèi)
 */
public class Whip extends CondimentDecorator {
    private Beverage beverage;

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

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Whip";
    }

    @Override
    public double cost() {
        return .50 + beverage.cost();
    }
}

(6)容量類(lèi)

/**
 * 大杯
 */
public class Big extends Capacity {
    private Beverage beverage;

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

    @Override
    public double cost() {
        return beverage.cost() + 0.20;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + " ,Big";
    }
}
/**
 * 中杯
 */

public class Medium extends Capacity {
    private Beverage beverage;

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

    @Override
    public double cost() {
        return beverage.cost() + 0.15;
    }

    @Override
    public String getDescription() {
        return this.beverage.getDescription() + " ,Medium";
    }
}
/**
 * 小杯
 */

public class Small extends Capacity {
    private Beverage beverage;

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

    @Override
    public double cost() {
        return beverage.cost() + 0.10;
    }

    @Override
    public String getDescription() {
        return this.beverage.getDescription() + " ,Small";
    }
}

(7)測(cè)試類(lèi)

public class StarbuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());

        Beverage beverage1 = new DarkRoast();
        beverage1 = new Mocha(beverage1);
        beverage1 = new Mocha(beverage1);
        beverage1 = new Whip(beverage1);
        System.out.println(beverage1.getDescription() + " $" + beverage1.cost());

        Beverage beverage2 = new HouseBlend();
        beverage2 = new Soy(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        beverage2 = new Big(beverage2);
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
    }
}

結(jié)果:

Espresso $1.99
DarkRoast,Mocha,Mocha,Whip $3.8900000000000006
HouseBlend,Soy,Mocha,Whip ,Big $2.09

1、認(rèn)識(shí)裝飾者模式

購(gòu)買(mǎi)咖啡時(shí),除了咖啡的各種口味以外,還可以加入各種調(diào)料,例如:蒸奶、豆?jié){、摩卡或奶蓋,星巴克會(huì)根據(jù)加入不同的調(diào)料收取不同的費(fèi)用,當(dāng)然還有大中小杯等等。

如果我們使用類(lèi)繼承的方式,會(huì)導(dǎo)致類(lèi)數(shù)目爆炸、設(shè)計(jì)死板,以及基類(lèi)加入的新功能并不適用于所有的子類(lèi)。

所以我們要采取不一樣的做法,我們以飲料為主體,然后采用調(diào)料類(lèi)、體積類(lèi)來(lái)修飾。

(1)拿一個(gè)深焙咖啡(DarkRoast)對(duì)象

(2)以摩卡(Mocha)對(duì)象來(lái)修飾

(3)以奶泡(Whip)來(lái)修飾

(4)以中杯(Medium)來(lái)修飾

(5)調(diào)用cost()方法,并依賴(lài)委托(delegate)將調(diào)料的價(jià)錢(qián)加上

2、定義

裝飾者模式:動(dòng)態(tài)地將責(zé)任附加到對(duì)象上,若要拓展功能,裝飾者提供了比繼承更有彈性的替代方案。

BD65E96F-442F-4A17-8CAD-429B18D95F1D_1_105_c.jpeg

3、設(shè)計(jì)原則:

開(kāi)放-關(guān)閉原則

類(lèi)應(yīng)該對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。

我們的目標(biāo)是允許類(lèi)容易拓展,在不修改現(xiàn)有代碼的情況下,就可搭配新的行為。

4、設(shè)計(jì)

5DC568F8-7135-4D6B-B40D-D48673A49C73_1_201_a.jpeg

代碼實(shí)現(xiàn):

(1)裝飾者總抽象類(lèi)

public abstract class Beverage {
    public String description = "Unknown Beverage";

    public String getDescription(){
        return description;
    }
    public abstract double cost();
}

(2)調(diào)料裝飾者 抽象類(lèi)

public abstract class CondimentDecorator extends Beverage {
    @Override
    public abstract String getDescription();
}

(3)容量裝飾者 抽象類(lèi)

public abstract class Capacity extends Beverage {
    @Override
    public abstract String getDescription();
}

(4)四種咖啡實(shí)現(xiàn)類(lèi)

/**
 * 深度烘焙咖啡類(lèi)
 */
public class DarkRoast extends Beverage {

    public DarkRoast(){
        this.description = "DarkRoast";
    }

    @Override
    public double cost() {
        return 2.99;
    }
}
/**
 * 貓屎咖啡
 */

public class Decat extends Beverage {

    public Decat(){
        this.description = "Decat";
    }

    @Override
    public double cost() {
        return 1.89;
    }
}
/**
 * 濃縮咖啡類(lèi)
 */
public class Espresso extends Beverage {

    public Espresso(){
        this.description = "Espresso";
    }

    @Override
    public double cost() {
        return 1.99;
    }
}
/**
 * 首選咖啡(星巴克咖啡名)
 */
public class HouseBlend extends Beverage {
    public HouseBlend() {
        description = "HouseBlend";
    }

    @Override
    public double cost() {
        return 0.89;
    }
}

(5)調(diào)料類(lèi)

/**
 * 摩卡  調(diào)料類(lèi)
 */
public class Mocha extends CondimentDecorator {
    private 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();
    }
}
/**
 * 大豆  調(diào)料類(lèi)
 */
public class Soy extends CondimentDecorator {
    private Beverage beverage;

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

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Soy";
    }

    @Override
    public double cost() {
        return .30 + beverage.cost();
    }
}
/**
 * 鮮奶  調(diào)料類(lèi)
 */
public class Whip extends CondimentDecorator {
    private Beverage beverage;

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

    @Override
    public String getDescription() {
        return beverage.getDescription() + ",Whip";
    }

    @Override
    public double cost() {
        return .50 + beverage.cost();
    }
}

(6)容量類(lèi)

/**
 * 大杯
 */
public class Big extends Capacity {
    private Beverage beverage;

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

    @Override
    public double cost() {
        return beverage.cost() + 0.20;
    }

    @Override
    public String getDescription() {
        return beverage.getDescription() + " ,Big";
    }
}
/**
 * 中杯
 */

public class Medium extends Capacity {
    private Beverage beverage;

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

    @Override
    public double cost() {
        return beverage.cost() + 0.15;
    }

    @Override
    public String getDescription() {
        return this.beverage.getDescription() + " ,Medium";
    }
}
/**
 * 小杯
 */

public class Small extends Capacity {
    private Beverage beverage;

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

    @Override
    public double cost() {
        return beverage.cost() + 0.10;
    }

    @Override
    public String getDescription() {
        return this.beverage.getDescription() + " ,Small";
    }
}

(7)測(cè)試類(lèi)

public class StarbuzzCoffee {
    public static void main(String[] args) {
        Beverage beverage = new Espresso();
        System.out.println(beverage.getDescription() + " $" + beverage.cost());

        Beverage beverage1 = new DarkRoast();
        beverage1 = new Mocha(beverage1);
        beverage1 = new Mocha(beverage1);
        beverage1 = new Whip(beverage1);
        System.out.println(beverage1.getDescription() + " $" + beverage1.cost());

        Beverage beverage2 = new HouseBlend();
        beverage2 = new Soy(beverage2);
        beverage2 = new Mocha(beverage2);
        beverage2 = new Whip(beverage2);
        beverage2 = new Big(beverage2);
        System.out.println(beverage2.getDescription() + " $" + beverage2.cost());
    }
}

結(jié)果:

Espresso $1.99
DarkRoast,Mocha,Mocha,Whip $3.8900000000000006
HouseBlend,Soy,Mocha,Whip ,Big $2.09
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容