8.Decorator-裝飾模式

Decorator 裝飾模式

  • 裝飾模式:
    裝飾模式又名包裝(Wrapper)模式。裝飾模式以對客戶端透明的方式擴展對象的功能,是繼承關係的一個替代方案。
    給一個對象增長一些新的功能,並且是動態的,要求裝飾對象和被裝飾對象實現同一個接口,裝飾對象持有被裝飾對象的實例。
    就功能而言,修飾模式相比生成子類更爲靈活,這樣能夠給某個對象而不是整個類添加一些功能。

它主要是解決:java

「過分地使用了繼承來擴展對象的功能」,因爲繼承爲類型引入的靜態特質,使得這種擴展方式缺少靈活性;
而且隨着子類的增多(擴展功能的增多),各類子類的組合(擴展功能的組合)會致使更多子類的膨脹(多繼承)。
繼承爲類型引入的靜態特質的意思是說以繼承的方式使某一類型要得到功能是在編譯時。
所謂靜態,是指在編譯時;動態,是指在運行時。markdown

  • 示例類圖:
    Decorator_umlapp

  • 示例代碼:ide

// Component
public interface Sender {
    public void send(String msg);
}
// ConcreteComponent
public class MailSender implements Sender {
    @Override
    public void send(String msg) {
        System.out.println("MailSender send : " + msg);
    }
}
public class SmsSender implements Sender {
    @Override
    public void send(String msg) {
        System.out.println("SmsSender send : " + msg);
    }
}

// Decorator接口或者抽象類
public abstract class DecoratorSender implements Sender {
    protected Sender sender;

    public DecoratorSender(Sender sender) {
        this.sender = sender;
    }

    @Override
    public void send(String msg) {
        sender.send(msg);
    }

}
// 具體實現Decorator接口或者繼承抽象類的類
public class DecoratorEncodeSender extends DecoratorSender {

    public DecoratorEncodeSender(Sender sender) {
        super(sender);
    }

    @Override
    public void send(String msg) {
        super.send(encode(msg));
    }
    // 爲sender對象發送的msg特殊編碼
    private String encode(String msg) {
        System.out.println("編碼處理...");
        return "###" + msg + "$$$";
    }
}

// 測試
public class DecoratorTest {

    public static void main(String[] args) {
        Sender sender = new MailSender();
        DecoratorSender decoratorSender = new DecoratorEncodeSender(sender);
        decoratorSender.send("郵箱信息...");

        new DecoratorEncodeSender(new SmsSender()).send("短信信息..");
        sender = new DecoratorEncodeSender(new SmsSender());
    }

}
  • Decorator裝飾模式的幾點要點:函數

    1. 經過採用組合、而非繼承的手法,Decorator模式實現了在運行時動態的擴展對象功能的能力,
      並且能夠根據須要擴展多個功能。避免了單獨使用繼承帶來的「靈活性差」和「多子類衍生問題」。測試

    2. Component類在Decorator模式中充當抽象接口的角色,不該該去實現具體的行爲。
      並且Decorator類對於Component類應該透明——換言之Component類無需知道Decorator類,
      Decorator類是從外部來擴展Component類的功能。this

    3. Decorator類在接口上表現爲is-a Component的繼承關係,即Decorator類繼承了Component類所具備的接口。
      但在實現上又表現爲has-a Component的組合關係,即Decorator類又使用了另一個Component類。
      咱們可使用一個或多個Decorator對象來「裝飾」一個Component對象,且裝飾後的對象仍然是一個Component對象。編碼

在這裏我想談一下個人理解:當咱們實例化一個Component對象後,要給這個對象擴展功能,
這時咱們把這個Component對象看成參數傳給Decorator的子類的構造函數——也就是擴展方法的功能類。
對於引用類型傳參時,實際上只是傳遞對象的地址,這樣,在功能擴展是,操做的應該是同一個對象。spa

  1. Decorator模式並不是解決「多子類衍生的多繼承」問題,Decorator模式應用的要點在於解決「主體類在多個方向上的擴展功能」——是爲「裝飾」的含義。
    Decorator是在運行時對功能進行組合。code

    • 裝飾器模式的應用場景:
  2. 須要擴展一個類的功能。

  3. 動態的爲一個對象增長功能,並且還能動態撤銷。(繼承不能作到這一點,繼承的功能是靜態的,不能動態增刪)

    • 缺點:產生過多類似的對象,不易排錯。
相關文章
相關標籤/搜索