10 裝飾模式

定義

裝飾模式(Decorator Pattern):動態地給一個對象增加一些額外的職責。就擴展功能而言,裝飾模式提供了一種比使用子類更加靈活的替代方案。

結構

  1. Component(抽象構件):它是具體構件和抽象裝飾類的共同父類,聲明瞭在具體構件中實現的業務方法,它的引入可以使客戶端以一致的方式處理未被裝飾的對象以及裝飾之後的對象,實現客戶端的透明操作。
  2. ConcreteComponent(具體構件):它是抽象構件類的子類,用於定義具體的構件對象,實現了在抽象構件中聲明的方法,裝飾類可以給它增加額外的職責(方法)。
  3. Decorator(抽象裝飾類):它是抽象構件的子類,用於給具體構建增加職責,但是具體職責在其子類中實現。它維護了一個指向抽象構件對象的引用,通過該引用可以調用裝飾之前的構件對象的方法,並通過其子類擴展該方法,以達到裝飾的目的。
  4. ConcreteDecorator(抽象裝飾類):它是抽象裝飾類的子類,負責向構件添加新的職責。每一個具體裝飾類都定義了一些新的行爲,它可以調用在抽象裝飾類中定義的方法,並可以增加新的方法用於擴充對象的行爲。

代碼

Component

public abstract class Component {
    
    public abstract void operation();
    
}

ConcreteComponent

public class ConcreteComponent extends Component {

    @Override
    public void operation() {
        System.out.println("ConcreteComponent");
    }

}

Decorator

public class Decorator extends Component {

    private Component component;

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

    @Override
    public void operation() {
        component.operation(); // 調用原有的業務方法
    }

}

ConcreteDecorator

public class ConcreteDecorator extends Decorator {

    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        addedBehavior();
    }

    /**
     * 新增業務方法
     */
    public void addedBehavior() {
        System.out.println("addedBehavior");
    }

}

擴展

新增具體構件

public class ConcreteComponent1 extends Component {

    @Override
    public void operation() {
        System.out.println("ConcreteComponent1");
    }

}

新增具體裝飾類

public class ConcreteDecorator1 extends Decorator {

    public ConcreteDecorator1(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        dosomething();
    }

    /**
     * 新增業務方法
     */
    public void dosomething() {
        System.out.println("dosomething");
    }

}

客戶端調用

Component component = new ConcreteComponent1();
Component decorator = new ConcreteDecorator1(component);
decorator.operation();

透明裝飾模式與半透明裝飾模式

  1. 透明裝飾模式

在透明裝飾模式中要求客戶端完全針對抽象編程,裝飾模式的透明性要求客戶端程序不應該將對象聲明爲具體構件類型或具體裝飾類型,而應該全部聲明爲抽象構件類型。對於客戶端而言,具體構件對象和具體裝飾對象沒有任何區別。

Component component, decorator;
component = new ConcreteComponent();
decorator = new ConcreteDecorator(component);
decorator.operation();
  1. 半透明裝飾模式

透明裝飾模式的設計難度較大,而且有時需要單獨調用新增的業務方法。爲了能夠調用大新增的方法,不得不用具體裝飾類型來定義裝飾後的對象,而具體構件類任然可以使用到抽象構件類型來定義,這種裝飾弄溼即爲半透明裝飾模式。也就是說,對於客戶端而言,具體構件類型無須關心,是透明的;但是具體裝飾類型必須執行,這是不透明的。

// 抽象構件類型定義
Component component = new ConcreteComponent();
component.operation();

// 使用具體裝飾類型定義
ConcreteDecorator decorator = new ConcreteDecorator(component);
component.operation();
component.addedBehavior();

優/缺點與適用環境

  1. 優點
  • 對於擴展一個對象的功能,裝飾模式比繼承更加靈話,不會導致類的個數急劇增加。
  • 可以通過一種動態的方式來擴展一個對象的功能,通過配置文件可以在運行時選擇不同的具體裝飾類,從而實現不同的行爲。
  • 可以對個對象進行多次裝飾,通過使用不同的具體裝飾類以及這些裝飾類的排列組合可以創造出很多不同行爲的組合,得到功能更加強大的對象。
  • 具體構件類與具體裝飾類可以獨立變化,用戶可以根據需要增加新的具體構件類和具體裝飾類,原有類庫代碼無須改變,符合開閉原則。
  1. 缺點
  • 在使用裝飾模式進行系統設計時將產生很多小對象,這些對象的區別在於它們之間相互連接的方式有所不同,而不是它們的類或者屬性值有所不同,大量小對象的產生勢必會佔用更多的系統資源,在一定程度上影響程序的性能。
  • 裝飾模式提供了一種比繼承更加靈活、機動的解決方案,但同時也意味着比繼承更加易於出錯,排錯也更困難,對於多次裝飾的對象,在調試時尋找錯誤可能需要逐級排查,較爲繁瑣。
  1. 適用環境
  • 在不影響其他對象的情況下以動態、透明的方式給單個對象添加職責。
  • 當不能採用繼承的方式對系統進行擴展或者採用繼承不利於系統擴展和維護時可以使用裝飾模式,不能採用繼承的情況主要有兩類:第一類是系統中存在大量獨立的擴展,爲支持每一種擴展或者擴展之間的組合將產生大量的子類,使得子類數目呈爆炸性增長;第二類是因爲類已定義爲不能被繼承(例如在Java語言中使用final關鍵宇修飾的類)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章