天天看點

設計模式---裝飾器模式

簡述

運作時,為原對象拓展新的行為。

相較于傳統的繼承來拓展新的行為,裝飾器模式更為的靈活多變,當然實作起來也更為複雜。

話不多說,看個優化案例吧。

優化案例

最初版v0

現有系統中有設定視窗Style的子產品,現在想增加一個圓角的樣式。以下是現有子產品的代碼。

class Style {    public void style() {
        System.out.println("設定Order");
    }}      

第一種傳統的修改方式。

class Style {
    public void style() {
        System.out.println("設定Order");
        System.out.println("設定Radius");
    }}      

雖然代碼簡單,但細想一下,如果我們日後仍然需要單獨設定Order的樣式怎麼辦。現在的代碼實作已經無法滿足了不是?

為此,我們可能會想到另一種方案。使用繼承。

class BaseStyle {
    public void style() {
        System.out.println("設定Order");
    }}class Radius extends BaseStyle {
    public void style() {
        super.style();
        System.out.println("設定Radius");
    }}      

确實,如果不在意類的命名的話,目前來看這确實是個好的選擇。請注意,隻是目前來看。設計不隻着眼與目前,而是需要放眼未來。什麼意思呢?比如,當未來需要添加一個Color樣式的時候怎麼辦,有人可能認為添加再添加一個BassStyle類的子類Color就好了;如果客戶就隻要一個單獨的Color樣式呢,或者說需要一個可以設定Radius和Color的樣式。再超前一些,客戶如果想要的是增加一個樣式,且可以與現有的任何一種或多種樣式随意組合呢?又該怎麼辦?傳統的繼承已經搞不了了呀。

别慌,最後這一種需求正好就是使用裝飾器模式的目的。我們來看看改進後的案例吧。

修改版v1

使用裝飾器模式優化上述需求,使得任意樣式間可以任意組合,這種任意組合包括任意種類和數量。

public interface Style {
    void style();}public class Order implements Style {
    @Override    public void style() {
        System.out.println("設定Order");
    }}
public class Radius implements Style {
    @Override    public void style() {
        System.out.println("設定Radius");
    }}
 public class Color implements Style {
    @Override
    public void style() {
        System.out.println("設定Color");
    }}public class OrderDecorator implements Style {
    private Style style;
    public OrderDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() {
        style.style();
        decorator();
    }
    private void decorator() {
        System.out.println("設定Order");
    }}
public class RadiusDecorator implements Style {
    private Style style;
    public RadiusDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() {
        style.style();
        decorator();
    }
    private void decorator() {
        System.out.println("設定Radius");
    }}
public class ColorDecorator implements Style {
    private Style style;
    public ColorDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() {
        style.style();
        decorator();
    }
    private void decorator() {
        System.out.println("設定Color");
    }}      

定義三個裝飾器類:​

​OrderDecorator​

​, ​

​RadiusDecorator​

​, ​

​ColorDecorator​

​分别實作​

​Style​

​接口,定義​

​decorator​

​方法用(動态拓展的核心方法之一)。調用完``target​

​的​

​style​

​方法後調用​

​decorator`方法實作功能的動态拓展。接着,看看用戶端如何使用。

public class Client {
    public static void main(String[] args) {
        Style style = new Order();
        Style style1 = new ColorDecorator(style);
        Style style2 = new RadiusDecorator(style1);
        style2.style();
    }}      

輸出結果:

設定Order設定Color設定Radius      

修改版v2

上述優化可以看到一些重複備援的代碼,還有再次優化的空間。以下是實作樣例。

public interface Style {
    void style();}public class Order implements Style {
    @Override
    public void style() {
        System.out.println("設定Order");
    }}
public class Radius implements Style {
   @Override    public void style() {
        System.out.println("設定Radius");
    }}
public class Color implements Style {
    @Override
    public void style() {
        System.out.println("設定Color");
    }}
public abstract class StyleDecorator implements Style {
 // 抽出共通建立裝飾類的高層抽象類
    protected Style style;
    public StyleDecorator(Style target) {
        this.style = target;
    }
    @Override
    public void style() {
 // style設定
        style.style();
        decorator();
    }
    protected abstract void decorator();
 // 裝飾方法
    }
public class OrderDecorator extends StyleDecorator {
    public OrderDecorator(Style target) {
        super(target);
    }
    @Override
    protected void decorator() {
        System.out.println("設定Order");
    }}
public class RadiusDecorator extends StyleDecorator {
    public RadiusDecorator(Style target) {
        super(target);
    }
    @Override
    protected void decorator() {
        System.out.println("設定Radius");
    }}public class ColorDecorator extends StyleDecorator {
    public ColorDecorator(Style target) {
        super(target);
    }
    @Override
    protected void decorator() {
        System.out.println("設定Color");
    }}      

用戶端的使用和輸出結果還是和v1一樣。

public class Client {
    public static void main(String[] args) {
        Style style = new Order();
        Style style1 = new ColorDecorator(style);
        Style style2 = new RadiusDecorator(style1);
        style2.style();
    }}      
設定Order設定Color設定Radius      

總結

優點

  1. 開發時可以自由組合各種各樣的功能。
  2. 新增的功能對于現有功能沒有任何的影響。

缺點

  1. 增加系統的複雜度。
  2. 對于開發人員的技術要求提高。

應用場景

  1. 需要靈活組合功能的場合。
  2. 限制繼承,但又想拓展類的功能的場合。