裝飾者模式

一、一個問題。

??或說國哥當年在創(chuàng)業(yè)開店---賣豆?jié){!因豆?jié){純。分店幾乎開遍全縣所有村,由于發(fā)展是在太快了,所以急需一套由計算機管理的自動化記賬系統(tǒng)。


繼承帶來的問題
類爆炸

二、裝飾者模式,看看它能為我們帶來什么驚喜吧!

??1、意圖

??動態(tài)的給一個對象添加一些額外的職責。就增加功能來說,Decorator模式相比生成子類更為靈活。該模式以對客戶透明的方式擴展對象的功能。

??2、適用環(huán)境

??在不影響其他對象的情況下,以動態(tài)、透明的方式給單個對象添加職責。
??當不能采用子類的方式進行擴充時。一種情況是,可能有大量獨立的擴展,為支持每一種組合將產生大量的子類。使得子類的數(shù)目呈現(xiàn)爆炸式增長。另外一種情況可能是因為類定義被隱藏,或類定義不能用于生成子類。

??3、類圖

??Component(被裝飾對象基類)
??定義對象的接口,可以給這些對象動態(tài)增加職責;

??concreateComponent(具體被裝飾的對象)
??定義具體的對象,Decorator可以給它增加額外的職責

??Decorator(裝飾者抽象類)
??維護指向Component實例的引用,定義與Component一致的接口;

??ConcreteDecorator(具體裝飾者)
??具體的裝飾對象,給內部持有的具體被裝飾對象增加具體的職責。

三、實例

1、涉及角色

抽象組件:定義一個抽象接口,來規(guī)范準備附加功能的類。
具體對象:將要被附加功能的類,實現(xiàn)抽象構建角色接口。
抽象裝飾者:持有對具體構件角色的引用并定義與抽象構建角色一致的接口。
具體裝飾:實現(xiàn)抽象裝飾者角色,負責為具體構件添加額外功能。

2、代碼實現(xiàn)

描述
Drink.java 被裝飾者對象的接口
SoyaBeanMilk.java 具體的被裝飾者對象
EggDecorator.java 具體裝飾者對象
SugarDecorator.java 具體裝飾者對象
BlankBeanDecorator.java 具體裝飾者對象
Decorator.java 裝飾者基類
Test.java 測試

項目目錄

Drink.java

package com.antiai.decorator;

public interface Drink {
    float cost(); // 計算價格
    String description(); // 描述
}

SoyaBean.java

package com.antiai.decorator;

/*
* 具體的被裝飾者類
* 豆?jié){
* */
public class SoyaBeanMilk implements Drink {
    @Override
    public float cost() {
        return 10f;
    }

    @Override
    public String description() {
        return "純豆?jié){";
    }
}

Decorator.java

package com.antiai.decorator;

/*
* 裝飾者基類
* */
public class Decorator implements Drink {
    private Drink drink; // 要裝飾的對象
    public Decorator(Drink drink){
        this.drink = drink;
    }

    @Override
    public float cost() {
        return drink.cost();
    }

    @Override
    public String description() {
        return drink.description();
    }
}

SugarDecorator

package com.antiai.decorator;

public class SugarDecorator extends Decorator {
    public SugarDecorator(Drink drink) {
        super(drink);
    }

    @Override
    public float cost() {
        return super.cost()+1.0f;
    }

    @Override
    public String description() {
        return super.description()+"+糖";
    }
}

BlankBeanDecorator

package com.antiai.decorator;

public class BlankBeanDecorator extends Decorator {
    public BlankBeanDecorator(Drink drink) {
        super(drink);
    }

    @Override
    public float cost() {
        return super.cost()+2.0f;
    }

    @Override
    public String description() {
        return super.description()+"+黑豆";
    }
}

EggDecorator

package com.antiai.decorator;

public class EggDecorator extends Decorator {
    public EggDecorator(Drink drink) {
        super(drink);
    }

    @Override
    public float cost() {
        return super.cost()+3.0f;
    }

    @Override
    public String description() {
        return super.description()+"+雞蛋";
    }
}

Test.java

package com.antiai.decorator;

public class Test {
    public static void main(String[] args) {
        Drink drink = new SoyaBeanMilk();
        SugarDecorator sugar = new SugarDecorator(drink);
        EggDecorator egg = new EggDecorator(sugar);
        BlankBeanDecorator blankBean = new BlankBeanDecorator(egg);

        System.out.println("你點的豆?jié){是:"+ blankBean.description());
        System.out.println("一共花了:"+blankBean.cost());
    }
}

四、裝飾者模式小結

oo原則:動態(tài)地將責任附加到對象上。想要擴展功能,裝飾者提供有別于繼承的另一種選擇。
要點
1、繼承屬于擴展形式之一,但不見得是達到彈性設計的最佳方案。
2、在我們的設計中,應該允許行為可以被拓展,而無需修改現(xiàn)有的代碼。
3、組合和委托可以用于在運行時動態(tài)地加上新的行為。
4、除了繼承,裝飾者模式也可以讓我們擴展行為。
5、裝飾者模式意味著一群裝飾者類,這些類用于包裝具體組件。
6、裝飾者類反映出被裝飾的組件類型(實際上,他們具有相同的類型,都經過接口或繼承實現(xiàn))。
7、裝飾者可以在被裝飾者的行為前面/后面加上自己的行為。甚至將裝飾者的整個行為取代掉。而達到特定的目的。
8、你可以有無數(shù)個裝飾者包裝一個對象。
9、裝飾者一般對組建的客戶是透明的,除非客戶程序依賴于組件的具體類型。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容