裝飾器模式和代理模式的區別

代理模式和裝飾器模式很像,這裏用【到咖啡館喝咖啡】做例子來說解。設計模式

基礎實現ide

定義一個咖啡的接口。this

public interface Coffee {
    /**
     * 打印當前咖啡裏有什麼
     */
    void printMaterial();
}

定義一個苦咖啡的實現。編碼

public class BitterCoffee implements Coffee {
    @Override
    public void printMaterial() {
        System.out.println("咖啡");
    }
}

定義一個默認的點咖啡邏輯。spa

@Test
public void orderCoffee {
    Coffee coffee = new BitterCoffee();
    coffee.printMaterial(); // 咖啡
}

裝飾器模式設計

你喝了一口咖啡,以爲有點苦,因而你就想加點糖。代理

定義一個咖啡裝飾器(加糖)。code

public class CoffeeDecorator implements Coffee {
    /**
     * 持有一個咖啡對象
     */
    private final Coffee coffee;

    public CoffeeDecorator(Coffee coffee) {
        this.coffee = coffee;
    }

    @Override
    public void printMaterial() {
        System.out.println("糖");
        this.coffee.printMaterial();
    }
}

定義一個咖啡加糖的應用邏輯。對象

@Test
public void addSugerIntoCoffee {
    Coffee coffee = new BitterCoffee(); // 點了一杯苦咖啡
    coffee = new SugarDecorator(coffee); // 給咖啡加了點糖
    coffee.printMaterial(); // 糖 咖啡
}

裝飾器適用場景:我有一個對象,可是這個對象的功能不能使我滿意(咖啡太苦了),我就拿裝飾器給他裝飾一下(給咖啡加糖)。blog

代理模式(靜態代理)

約好的朋友來了,要給她點一杯咖啡,你知道咖啡很苦,決定直接點一杯加了糖的咖啡給她。

定義一個加糖咖啡的類。

public class CoffeeProxy implements Coffee {
    private final Coffee coffee;

    public CoffeeProxy() {
        this.coffee = new BitterCoffee();
    }

    @Override
    public void printMaterial() {
        System.out.println("糖");
        this.coffee.printMaterial();
    }
}

而後定義一個點加糖咖啡的邏輯。

@Test
public void addSugerIntoCoffee {
    Coffee coffee = new CoffeeProxy();
    coffee.printMaterial(); // 糖 咖啡
}

裝飾器和代理模式的區別

對裝飾器模式來講,裝飾者(Decorator)和被裝飾者(Decoratee)都實現一個接口。對代理模式來講,代理類(Proxy Class)和真實處理的類(Real Class)都實現同一個接口。此外,不論咱們使用哪個模式,均可以很容易地在真實對象的方法前面或者後面加上自定義的方法。

在上面的例子中,裝飾器模式是使用的調用者從外部傳入的被裝飾對象(coffee),調用者只想要你把他給你的對象裝飾(增強)一下。而代理模式使用的是代理對象在本身的構造方法裏面new的一個被代理的對象,不是調用者傳入的。調用者不知道你找了其餘人,他也不關心這些事,只要你把事情作對了便可。

裝飾器模式關注於在一個對象上動態地添加方法,而代理模式關注於控制對對象的訪問。換句話說,用代理模式,代理類能夠對它的客戶隱藏一個對象的具體信息。所以當使用代理模式的時候,咱們經常在一個代理類中建立一個對象的實例;當使用裝飾器模式的時候,咱們一般的作法是將原始對象做爲一個參數傳給裝飾器的構造器。

裝飾器模式和代理模式的使用場景不同,好比IO流使用的是裝飾者模式,能夠層層增長功能。而代理模式則通常是用於增長特殊的功能,有些動態代理不支持多層嵌套。

代理和裝飾其實從另外一個角度更容易去理解兩個模式的區別:代理更多的是強調對對象的訪問控制,好比說,訪問A對象的查詢功能時,訪問B對象的更新功能時,訪問C對象的刪除功能時,都須要判斷對象是否登錄,那麼我須要將判斷用戶是否登錄的功能抽提出來,並對A對象、B對象和C對象進行代理,使訪問它們時都須要去判斷用戶是否登錄,簡單地說就是將某個控制訪問權限應用到多個對象上;而裝飾器更多的強調給對象增強功能,好比說要給只會唱歌的A對象添加跳舞功能,添加說唱功能等,簡單地說就是將多個功能附加在一個對象上。

因此,代理模式注重的是對對象的某一功能的流程把控和輔助,它能夠控制對象作某些事,重心是爲了借用對象的功能完成某一流程,而非對象功能如何。而裝飾模式注重的是對對象功能的擴展,不關心外界如何調用,只注重對對象功能增強,裝飾後仍是對象自己。

總結

對於代理類,如何調用對象的某一功能是思考重點,而不須要兼顧對象的全部功能;對於裝飾類,如何擴展對象的某一功能是思考重點,同時也須要兼顧對象的其餘功能,由於再怎麼裝飾,本質也是對象自己,要擔負起對象應有的職責,被裝飾者的職責一旦增長,做爲裝飾類也須要有相應的擴展,必然會形成編碼的負擔。

設計模式自己是爲了提高代碼的可擴展性,靈活應用便可,沒必要生搬硬套,非要分出個因此然來,裝飾器模式和代理模式的區別也是如此。

 

"咱們提着過去,走向人羣。"

相關文章
相關標籤/搜索