代理模式和裝飾器模式很像,這裏用【到咖啡館喝咖啡】做例子來說解。設計模式
基礎實現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對象添加跳舞功能,添加說唱功能等,簡單地說就是將多個功能附加在一個對象上。
因此,代理模式注重的是對對象的某一功能的流程把控和輔助,它能夠控制對象作某些事,重心是爲了借用對象的功能完成某一流程,而非對象功能如何。而裝飾模式注重的是對對象功能的擴展,不關心外界如何調用,只注重對對象功能增強,裝飾後仍是對象自己。
總結
對於代理類,如何調用對象的某一功能是思考重點,而不須要兼顧對象的全部功能;對於裝飾類,如何擴展對象的某一功能是思考重點,同時也須要兼顧對象的其餘功能,由於再怎麼裝飾,本質也是對象自己,要擔負起對象應有的職責,被裝飾者的職責一旦增長,做爲裝飾類也須要有相應的擴展,必然會形成編碼的負擔。
設計模式自己是爲了提高代碼的可擴展性,靈活應用便可,沒必要生搬硬套,非要分出個因此然來,裝飾器模式和代理模式的區別也是如此。
"咱們提着過去,走向人羣。"