java 設計模式:裝飾者模式

簡單詳解:

1、概念

動態地給一個對象添加一些額外的職責。就增加功能來說, 裝飾模式相比生成子類更爲靈活。該模式以對客戶端透明的方式擴展對象的功能。

2、使用場景

  1. 在不影響其他對象的情況下,以動態、透明的方式給單個對象添加職責。和繼承類似添加相應的職責。
  2. 當不能採用生成子類的方法進行擴充時。一種情況是,可能有大量獨立的擴展,爲支持每一種組合將產生大量的子類,使得子類數目呈爆炸性增長。另一種情況可能是因爲類定義被隱藏,或類定義不能用於生成子類。

3、UML結構圖分析

  • 抽象構件(Component)角色:給出一個抽象接口,已規範準備接收附加責任的對象。
  • 具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類
  • 裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。
  • 具體裝飾(ConcreteDecorator)角色:負責給構件對象“貼上”附加的責任。

4、實際代碼分析

/**
 * 裝飾類Component,所有類的父類
 */
public interface Component {

    void sampleOperation();
}

/**
 * 實現抽象部件,具體裝飾過程還是交給子類實現
 */
public class Decorator implements Component {

    private Component component;
    public Decorator(Component component){
        this.component = component;
    }

    @Override
    public void sampleOperation() {
        component.sampleOperation();
    }

}

/**
 * 需要裝扮的類
 */
public class ConcreteComponent implements Component{
    @Override
    public void sampleOperation() {

    }
}

/**
 * 具體實現
 */
public class ConcreateDecoratorA extends Decorator{
    public ConcreateDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void sampleOperation() {
        super.sampleOperation();
        addPingShengm();
    }

    /**
     * 新增業務方法
     */
    private void addPingShengm() {
        System.out.println("添加繪彩1");
    }
}

/**
 * 具體實現
 */
public class ConcreateDecoratorB extends Decorator{
    public ConcreateDecoratorB(Component component) {
        super(component);
    }


    @Override
    public void sampleOperation() {
        super.sampleOperation();
        addPingShengm();
    }


    /**
     * 新增業務方法
     */
    private void addPingShengm() {
        System.out.println("添加繪彩2");
    }
}

舉一個實際例子:

工廠需要產生多種水杯,有瓶身繪彩,有不鏽鋼蓋被子,也有不鏽鋼蓋和瓶身繪彩的杯子。(等各種需求)

假如說採用繼承子類的方式。如下code:

/**
 * 創建水杯的接口包含四個方法,底座,蓋子,瓶身,一個實現功能product
 */
public interface IShuiBei {

    void dizuo();

    void gaizi();

    void pingsheng();

    void product();

}
/**
 * 水晶杯實現類
 */
public class ShuiJInBei  implements IShuiBei,Component {
    @Override
    public void dizuo() {
        System.out.println("水晶底座");
    }

    @Override
    public void gaizi() {
        System.out.println("水晶蓋子");
    }

    @Override
    public void pingsheng() {
        System.out.println("水晶瓶身");
    }

    @Override
    public void product() {
        dizuo();
        gaizi();
        pingsheng();
    }
}

/**
 * 添加繪彩的水晶杯
 */
public class HuiCaiShuiJinBei extends ShuiJInBei{
    @Override
    public void pingsheng() {
        super.pingsheng();
        System.out.println("添加繪彩");
    }
}
/**
 * 不鏽鋼杯子蓋的水晶杯
 */
public class HuiJinGangGaiBei extends ShuiJInBei{
    @Override
    public void gaizi() {
        System.out.println("不鏽鋼杯蓋");
    }
}

/**
 * 不鏽鋼杯子蓋的水晶杯帶彩繪
 */
public class HuiCaiShuiJinGangGaiBei extends ShuiJInBei{
    @Override
    public void gaizi() {
        System.out.println("不鏽鋼杯蓋");
    }
 @Override
    public void pingsheng() {
        super.pingsheng();
        System.out.println("添加繪彩");
    }
}

//運行
        HuiCaiShuiJinBei huiCaiShuiJinBei = new HuiCaiShuiJinBei();
        HuiCaiShuiJinGangGaiBei huiCaiShuiJinGangGaiBei = new HuiCaiShuiJinGangGaiBei();
        ShuiJInBei shuiJInBei = new ShuiJInBei();
        huiCaiShuiJinBei.product();
        huiCaiShuiJinGangGaiBei.product();
        shuiJInBei.product();

一共創建三個子類,一個父類,當然如果需求更多的話,子類會不斷的增加。

裝飾類實現如上功能code:

/**
 * 實現抽象部件
 */
public class ShuijinbeiDecorator implements IShuiBei{
    IShuiBei iShuiBei;
    public ShuijinbeiDecorator(IShuiBei iShuiBei){
        this.iShuiBei = iShuiBei;
    }

    @Override
    public void dizuo() {
        iShuiBei.dizuo();
    }

    @Override
    public void gaizi() {
        iShuiBei.gaizi();
    }

    @Override
    public void pingsheng() {
        iShuiBei.pingsheng();
    }

    @Override
    public void product() {
        dizuo();
        gaizi();
        pingsheng();
    }
}
/**
 * 鋼蓋實現類
 */
public class GangGaiDecorator extends ShuijinbeiDecorator{
    public GangGaiDecorator(IShuiBei iShuiBei) {
        super(iShuiBei);
    }

    @Override
    public void gaizi() {
        System.out.println("不鏽鋼杯蓋");
    }
}

/**
 * 彩繪實現類
 */
public class CaihuiDecorator extends ShuijinbeiDecorator{
    public CaihuiDecorator(IShuiBei iShuiBei) {
        super(iShuiBei);
    }

    @Override
    public void pingsheng() {
        super.pingsheng();
        System.out.println("添加繪彩");
    }
}
//運行
        IShuiBei iShuiBei = new ShuiJInBei();
        iShuiBei.product();
        iShuiBei = new CaihuiDecorator(iShuiBei);
        iShuiBei.product();
        iShuiBei = new GangGaiDecorator(iShuiBei);
        iShuiBei.product();
        iShuiBei = new ShuiJInBei();
        iShuiBei = new GangGaiDecorator(iShuiBei);
        iShuiBei.product();

看到如上代碼你大概會恍然大悟,裝飾模式如果在你的子類特別多,用裝飾模式很好,但是比較容易出錯哦。

裝飾模式的優點

  1. 裝飾模式與繼承關係的目的都是要拓展對象的功能,但是裝飾模式可以提供比繼承更多的靈活性。
  2. 裝飾模式允許系統動態決定“貼上”一個需要的“裝飾”,或者“除掉”一個不需要的“裝飾”。繼承關係則不同,繼承關係是靜態的,它在系統運行前就決定了。
  3. 可以對一個對象進行多次裝飾,通過使用不同的具體裝飾類以及這些裝飾類的排列組合。

裝飾模式的缺點

由於使用裝飾模式,可以比使用繼承關係需要較少數目的類。使用較少的類,當然使設計比較易於進行。但是,在另外一方面,使用裝飾模式會產生比使用繼承關係所產生的更多的對象。而更多的對象會使得查找錯誤更爲困難,特別是這些對象在看上去極爲相似的時候。

裝飾模式在Android中的實際應用

context類簇

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章