裝飾模式

1 定義

裝飾模式也成為包裝模式,此設(shè)計(jì)模式屬于結(jié)構(gòu)型模式。
定義:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的職責(zé)。就增加功能來(lái)說(shuō),裝飾模式相比生成子類(lèi)更為靈活。

模式結(jié)構(gòu)

角色介紹

  • Component:抽象組件
    可以是一個(gè)接口或者抽象類(lèi),定義我們最核心的對(duì)象,也就是被裝飾的原始對(duì)象。
  • ConcreteComponent:組件的具體實(shí)現(xiàn)
    Component類(lèi)的基本實(shí)現(xiàn),也就是要裝飾的具體對(duì)象。
  • Decorator:抽象裝飾者
    作用是為了裝飾我們的組件對(duì)象,其內(nèi)部必有一個(gè)指向Component對(duì)象的引用。
  • ConcreteDecoratorA:抽象裝飾者的具體實(shí)現(xiàn)。
  • ConcreteDecoratorB:抽象裝飾者的具體實(shí)現(xiàn)。

通用模式代碼

  • 抽象組件,被裝飾的原始對(duì)象
public abstract class Component {

    /**
     * 抽象的方法,可以有多個(gè)
     */
    public abstract void operate();
}
  • 組件的具體實(shí)現(xiàn),即被裝飾的具體對(duì)象
public class ConcreteComponent extends Component{

    @Override
    public void operate() {
        // 在這里寫(xiě)你的邏輯
    }
}
  • 抽象裝飾者,其內(nèi)部一定要有一個(gè)指向組件對(duì)象的引用。
public class Decorator extends Component{

    private Component mComponent; // 持有一個(gè)Component對(duì)象的引用
    
    /**
     * 構(gòu)造方法
     * @param component
     */
    public Decorator(Component component){
        this.mComponent=component;
    }

    @Override
    public void operate() {
        mComponent.operate();
    }
}
  • 抽象裝飾者的具體實(shí)現(xiàn)
public class ConcreteDecoratorA extends Decorator{

    /**
     * 構(gòu)造方法
     *
     * @param component
     */
    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operate() {
         // 裝飾方法A和B的調(diào)用順序可變
        operateA();
        super.operate();
        operateB();
    }

    /**
     * 自定義的裝飾方法
     */
    public void operateA(){
        // 裝飾邏輯
    }

    /**
     * 自定義的裝飾方法
     */
    public void operateB(){
        // 裝飾邏輯
    }

}
public class ConcreteDecoratorB extends Decorator{

    /**
     * 構(gòu)造方法
     *
     * @param component
     */
    public ConcreteDecoratorB(Component component) {
        super(component);
    }


    @Override
    public void operate() {
         // 裝飾方法A和B的調(diào)用順序可變
        operateA();
        super.operate();
        operateB();
    }

    /**
     * 自定義的裝飾方法
     */
    public void operateA(){
        // 裝飾邏輯
    }

    /**
     * 自定義的裝飾方法
     */
    public void operateB(){
        // 裝飾邏輯
    }
    
}
  • 測(cè)試代碼
 // 構(gòu)造被裝飾的對(duì)象
        Component component=new ConcreteComponent();
        // 根據(jù)組件對(duì)象構(gòu)造裝飾者對(duì)象A并調(diào)用,此時(shí)相當(dāng)于給組件對(duì)象添加裝飾者A的功能方法
        Decorator decoratorA=new ConcreteDecoratorA(component);
        decoratorA.operate();
        // 根據(jù)組件對(duì)象構(gòu)造裝飾者對(duì)象B并調(diào)用,此時(shí)相當(dāng)于給組件對(duì)象添加裝飾者B的功能方法
        Decorator decoratorB=new ConcreteDecoratorB(component);
        decoratorB.operate();

三 實(shí)例

我們?cè)僖灾谱髂滩铻槔?,?a href="http://www.itdecent.cn/p/3a7eb444b466" target="_blank">橋接模式里,我們實(shí)現(xiàn)了奶茶兩個(gè)維度的變化,大小杯和加不加糖。在裝飾模式下,我們要實(shí)現(xiàn)裝飾一杯奶茶,動(dòng)態(tài)地給奶茶添加一些功能。比如加冰,加藍(lán)莓,加珍珠,計(jì)算價(jià)格等。

  • 抽象組件,被裝飾的原始對(duì)象,在我們的實(shí)例是指制作一杯飲料
/*
 * 抽象組件,被裝飾的原始對(duì)象
 * @author Jackson
 * @version 1.0.0
 * since 2019 03 13
 */
public abstract class Beverage {

    /**
     * 抽象方法,制作飲料
     */
    public abstract void makeBeverage();

}
  • 組件的具體實(shí)現(xiàn),被裝飾的具體對(duì)象,在我們的實(shí)例,制作一杯奶茶
/*
 * 組件的具體實(shí)現(xiàn),被裝飾的具體對(duì)象
 * @author Jackson
 * @version 1.0.0
 * since 2019 03 13
 */
public class MilkTea extends Beverage {

    @Override
    public void makeBeverage() {
        // 奶茶的基本邏輯
        System.out.println("     添加奶茶    ");
    }
}
  • 抽象的裝飾者,其內(nèi)部保持一個(gè)被裝飾類(lèi)的引用
/*
 * 抽象的裝飾者
 * @author Jackson
 * @version 1.0.0
 * since 2019 03 13
 */
public abstract class Decorator extends Beverage {

    protected Beverage mBeverage; // 其內(nèi)部保持一個(gè)被裝飾類(lèi)的引用

    /**
     * 構(gòu)造方法
     * @param beverage
     */
    public Decorator(Beverage beverage){
        this.mBeverage=beverage;
    }

    @Override
    public void makeBeverage() {
        // 調(diào)用Beverage的makeBeverage()方法)
        mBeverage.makeBeverage();
    }
}
  • 具體裝飾者,加藍(lán)莓,加冰,加藍(lán)莓的奶茶
/*
 * 具體裝飾者,加藍(lán)莓
 * @author Jackson
 * @version 1.0.0
 * since 2019 03 13
 */
public class BlueberryDecorator extends Decorator{
    /**
     * 構(gòu)造方法
     *
     * @param beverage
     */
    public BlueberryDecorator(Beverage beverage) {
        super(beverage);
    }


    @Override
    public void makeBeverage() {
        // 順序:加冰--加飲料--加藍(lán)莓--收錢(qián),順序按照需求可變
        addIce();
        super.makeBeverage();
        addBlueberry();
        price();

    }

    /**
     * 添加冰塊
     */
    private void addIce(){
        System.out.println("    添加冰塊   ");
    }

    /**
     * 添加藍(lán)莓
     */
    private void addBlueberry(){
        System.out.println("     添加藍(lán)莓    ");
    }

    /**
     * 計(jì)算價(jià)格
     */
    private void price(){
        System.out.println("     藍(lán)莓奶茶的價(jià)格是5元    ");
    }

}
    • 具體裝飾者,加珍珠的奶茶
/*
 * 具體裝飾者,珍珠奶茶
 * @author Jackson
 * @version 1.0.0
 * since 2019 03 13
 */
public class PearlDecorator extends Decorator{
    /**
     * 構(gòu)造方法
     *
     * @param beverage
     */
    public PearlDecorator(Beverage beverage) {
        super(beverage);
    }


    @Override
    public void makeBeverage() {
        // 順序:收錢(qián)--加珍珠丸子--加飲料,順序按照需求可變
        price();
        addPearl();
        super.makeBeverage();
    }

    /**
     * 添加珍珠丸子
     */
    private void addPearl(){
        System.out.println("   添加珍珠丸子   ");
    }

    /**
     * 計(jì)算價(jià)格
     */
    private void price(){
        System.out.println("   珍珠奶茶的價(jià)格是6元   ");
    }
}
  • 測(cè)試代碼
 // 首先要現(xiàn)有一杯奶茶
 MilkTea milkTea=new MilkTea();
 System.out.println("------制作藍(lán)莓奶茶-------");
 // 制作藍(lán)莓奶茶
  BlueberryDecorator blueberryDecorator=new BlueberryDecorator(milkTea);
  blueberryDecorator.makeBeverage();
  // 制作珍珠奶茶
  System.out.println("------制作珍珠奶茶-------");
  PearlDecorator pearlDecorator=new PearlDecorator(milkTea);
  pearlDecorator.makeBeverage();
運(yùn)行結(jié)果

四 優(yōu)點(diǎn)

  • 比繼承更靈活
    裝飾模式比繼承更加靈活,繼承是靜態(tài)的,而且一旦繼承,所有子類(lèi)都有一樣的功能,而裝飾模式把功能分離到每個(gè)裝飾器中,然后通過(guò)組合的方式,組合的方式?jīng)Q定裝飾后對(duì)象的最終功能。
  • 更容易復(fù)用功能
    裝飾模式把一系列復(fù)雜的功能分散到每個(gè)裝飾器中,一般一個(gè)裝飾器只實(shí)現(xiàn)一個(gè)功能,從而可以更好地復(fù)用裝飾器。

五 使用場(chǎng)景

  • 需要擴(kuò)展一個(gè)類(lèi)的功能,或者給一個(gè)類(lèi)增加附加功能時(shí)可以考慮使用裝飾者模式。
?著作權(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)容