天天看點

【設計模式】——裝飾器模式VS代理模式

最近在學習Spring源碼,尤其是在學習FactoryBean的時候,有涉及到裝飾器模式,再結合自己之前學習的設計模式,代理模式覺得和裝飾器模式很相似,但是仔細研究後有各有不同,在這篇文章中整理下,希望可以幫助到需要的朋友。

裝飾器模式

定義:動态地給一個對象添加一些額外的職責,同時又不改變其結構,就增加功能來說裝飾模式比生成子類更為靈活。

【設計模式】——裝飾器模式VS代理模式

Component是定義一個對象接口,可以給這些對象動态的添加職責,ConcreteComponent是定義一個具體的對象,也可以給這個對象動态添加一些職責。Decorator,裝飾抽象類,繼承Component,從外類來擴充Component類的功能,但對于Component來說,是無需知道Decorator的存在的。至于ConcreteDecorator就是具體的裝飾對象,起到給Component添加職責的功能。

主要解決:一般的,我們為了擴充一個類經常使用繼承方式實作,由于繼承為類引入靜态特征,并且随着擴充功能的增多,子類會很膨脹。

何時使用:在不想增加很多子類的情況下擴充類。

如何解決:将具體功能職責劃分,同時繼承裝飾者模式。

關鍵代碼: 1、Component 類充當抽象角色,不應該具體實作。 2、修飾類引用和繼承 Component 類,具體擴充類重寫父類方法。

優點:裝飾類和被裝飾類可以獨立發展,不會互相耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動态擴充一個實作類的功能。

缺點:多層裝飾比較複雜。

使用場景: 1、擴充一個類的功能。 2、動态增加功能,動态撤銷。

注意事項:可代替繼承。

實作代碼

//充當抽象角色,不應該具體實作
public interface Component {

    void Operation();
}

//有一個具體的對象
public class ConcreteComponent implements Component {

    @Override
    public void Operation() {
        System.out.println("對象具體操作");
    }
}

//裝飾抽象類繼承Component
public abstract class Decorator implements Component {

    protected Component component;

    public void setComponent(Component component) {
        this.component = component;
    }

    @Override
    public void Operation() {
        if (component != null) {
            component.Operation();
        }
    }
}

//裝飾的具體實作類
public class ConcreteDecoratorA extends Decorator {

    @Override
    public void Operation() {
        super.Operation();
        System.out.println("具體裝飾對象A的操作");
    }
}

public class ConcreteDecoratorB extends Decorator {
    @Override
    public void Operation() {
        super.Operation();
        System.out.println("具體裝飾對象B的操作");
    }
}


 public static void main(String[] args) {
        ConcreteComponent component = new ConcreteComponent();
        ConcreteDecoratorA decoratorA = new ConcreteDecoratorA();
        ConcreteDecoratorB decoratorB = new ConcreteDecoratorB();

        //裝飾模式:首先用ConcreteComponent執行個體化對象component,
        //然後用ConcreteDecoratorA的執行個體化對象decoratorA包裝component
        //最後用ConcreteDecoratorB的執行個體化對象decoratorB包裝decoratorA
        decoratorA.setComponent(component);
        decoratorB.setComponent(decoratorA);

        decoratorB.Operation();
    }      
【設計模式】——裝飾器模式VS代理模式

原理:裝飾模式利用 setComponent來對對象進行包裝,這樣每個裝飾對象的實作和如何使用這個對象分離開了。每個裝飾對象隻關心自己的功能,不需要關心如何被添加到哦對象鍊中。

代理模式

定義:為其他對象提供一種代理以控制對這個對象的通路。

【設計模式】——裝飾器模式VS代理模式

主要解決:在直接通路對象時帶來的問題,比如說:要通路的對象在遠端的機器上。在面向對象系統中,有些對象由于某些原因(比如對象建立開銷很大,或者某些操作需要安全控制,或者需要程序外的通路),直接通路會給使用者或者系統結構帶來很多麻煩,我們可以在通路此對象時加上一個對此對象的通路層。

何時使用:想在通路一個類時做一些控制。

如何解決:增加中間層。

關鍵代碼:實作與被代理類組合。

應用執行個體: 1、Windows 裡面的快捷方式。 2、豬八戒去找高翠蘭結果是孫悟空變的,可以這樣了解:把高翠蘭的外貌抽象出來,高翠蘭本人和孫悟空都實作了這個接口,豬八戒通路高翠蘭的時候看不出來這個是孫悟空,是以說孫悟空是高翠蘭代理類。 3、買火車票不一定在火車站買,也可以去代售點。 4、一張支票或銀行存單是賬戶中資金的代理。支票在市場交易中用來代替現金,并提供對簽發人賬号上資金的控制。 5、spring aop。

優點: 1、職責清晰。 2、高擴充性。 3、智能化。

缺點: 1、由于在用戶端和真實主題之間增加了代理對象,是以有些類型的代理模式可能會造成請求的處理速度變慢。 2、實作代理模式需要額外的工作,有些代理模式的實作非常複雜。

使用場景:按職責來劃分,通常有以下使用場景: 1、遠端代理。 2、虛拟代理。 3、Copy-on-Write 代理。 4、保護(Protect or Access)代理。 5、Cache代理。 6、防火牆(Firewall)代理。 7、同步化(Synchronization)代理。 8、智能引用(Smart Reference)代理。

實作代碼

public interface Subject {
    void request();
}

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("真實的請求");
    }
}

public class Proxy implements Subject {

    private Subject realSubject;


    @Override
    public void request() {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        realSubject.request();
        System.out.println("代理請求也被執行");
    }
}


public class Demo {
    public static void main(String[] args) {
        Proxy proxy = new Proxy();

        proxy.request();
    }
}      
【設計模式】——裝飾器模式VS代理模式

裝飾器模式和代理模式相同點以及不同點

相同點

兩種從設計模式分類來看都屬于結構型,因為兩者均使用了組合關系。其次兩者都能實作對對象方法進行增強處理的效果。

不同點

代理模式,注重對對象某一功能的流程把控和輔助。它可以控制對象做某些事,重心是為了借用對象的功能完成某一流程,而非對象功能如何。

裝飾模式,注重對對象功能的擴充,它不關心外界如何調用,隻注重對對象功能的加強,裝飾後還是對象本身。

舉個例子說明兩者不同之處,代理和裝飾其實從另一個角度更容易去了解兩個模式的差別:代理更多的是強調對對象的通路控制,比如說,通路A對象的查詢功能時,通路B對象的更新功能時,通路C對象的删除功能時,都需要判斷對象是否登陸,那麼我需要将判斷使用者是否登陸的功能抽提出來,并對A對象、B對象和C對象進行代理,使通路它們時都需要去判斷使用者是否登陸,簡單地說就是将某個控制通路權限應用到多個對象上;而裝飾器更多的強調給對象加強功能,比如說要給隻會唱歌的A對象添加跳舞功能,添加說唱功能等,簡單地說就是将多個功能附加在一個對象上。

是以,代理模式注重的是對對象的某一功能的流程把控和輔助,它可以控制對象做某些事,重心是為了借用對象的功能完成某一流程,而非對象功能如何。而裝飾模式注重的是對對象功能的擴充,不關心外界如何調用,隻注重對對象功能加強,裝飾後還是對象本身。 

總結