Provide a surrogate or placeholder for another object to control access to it(爲其餘對象提供一種代理以控制對這個對象的訪問)設計模式
代理是基本的設計模式之一,它是你爲了提供額外或者不一樣的行爲,而插入的用來代替」實際對象「的對象。這些操做一般是涉及到與」實際對象「的通訊。網絡
舉個現實中和的例子:假設你有一套房子要出租,一種方法是你直接去網上發佈出租信息,而後直接帶要租房子的人來看房子,可是可能你很忙,你沒有時間去處理這些事情,因此你能夠去找中介,讓中介幫你處理這些瑣碎事情,中介實際上就是你的代理。原本是你要作的事情,如今中介幫助你一一處理。當咱們須要租房子時,只能找房屋中介,而不能找房東了,由於房東已經和房屋中介簽定了協議。因此房屋中介代理的存在就是爲了攔截咱們對於房東的直接訪問。ide
下面在代碼中體現出上面的例子this
如今有一個House
,有價格和顏色兩個屬性。設計
class Home{ Integer price; String color; -----get.set方法 }
有個房主的接口,每一個房主都具備出租的功能。代理
interface Homeowner{ public void LeaseHouse(Home home); }
如今有一個真實的房主實現了這個接口code
class RealHomeowner implements Homeowner{ @Override public void LeaseHouse(Home home) { System.out.println("房價是 "+ home.price); System.out.println("房子顏色是 "+ home.color); } }
如今有一個房屋代理,房屋代理也具有出租的功能,可是他出租的是和他簽定協議房主的房子。在和房主簽定協議以後他會對房子進行處理,而且將價格提升。對象
class HomeProxy implements Homeowner{ private Homeowner homeowner; public HomeProxy(Homeowner homeowner){ this.homeowner = homeowner; } @Override public void LeaseHouse(Home home) { System.out.println("裝修房子"); home.color="red"; System.out.println("提高價格"); home.price=home.price+1000; homeowner.LeaseHouse(home); } }
當房屋代理將房子整理好了之後,就將房源信息放入到網上供人們選擇接口
public static void consume(Homeowner homeowner,Home home){ if (homeowner instanceof HomeProxy){ homeowner.LeaseHouse(home); } else { System.out.println("請找房屋代理"); } }
在主方法中調用consume()
方法事務
public class ProxyDemo { public static void main(String[] args) { consume(new HomeProxy(new RealHomeowner()),new Home(1000,"black")); System.out.println("--------------------"); consume(new RealHomeowner(),new Home(1000,"black")); } }
發現直接和房東直租已經被拒絕了,只能經過代理進行租房。打印信息以下:
裝修房子 提高價格 房價是 2000 房子顏色是 red -------------------- 請找房屋代理
從上面能夠看出代理其實分爲三個角色:
抽象的主題角色:只是業務類型的定義。
具體的主題角色:也叫作被代理角色,是業務邏輯的真正執行者。
代理主題角色: 也叫作委託類、代理類。它負責對真實角色的應用,把全部抽象主題類定義的方法限制委託給真實主題角色實現,而且在真實主題角色處理完畢先後作預處理和藹後處理工做。
在任什麼時候候,只要你想要從額外的操做從「實際的對象」分離到不一樣的地方,特別是當你但願可以很容易的作出修改,從沒有使用額外操做轉爲使用這些操做,或者反過來時,代理就顯得頗有用。
仍是剛纔的現實的例子,咱們爲何要把房子給房屋代理?
爲其餘對象提供一種代理以控制對這個對象的訪問。在某些狀況下,一個客戶不想或者不能直接引用另外一個對象,而代理對象能夠在客戶端和目標對象之間起到中介的做用
對應到代碼中的意思就是:若是你在北京要處理美國的房子,每次有人想租房子,或者你租的房子出現了問題,你都得坐飛機回去和房客進行交涉或者維修。代碼中最多見的就是Web Service
的工做原理,即你只是想和另外一臺機器進行通訊,你不想管中間的通訊原理,例如網絡打包、通訊、解包等一系列複雜的問題,因此咱們使用代理將這一系列通訊的問題進行了包裝,再由代理進行通訊的功能。
對應到代碼中的意思就是:一個類的單一職能原則,對於房東來講,只會租房的功能,可是若是不裝修,不打理的話是很難租出去的,因此交給了房屋代理,房屋代理進行裝修,後期整理在進行出租。代碼中常見的實現就是對於權限的過濾,一個類有一個功能,而這個功能只適合一部分的用戶使用,因此利用代理進行權限的過濾。
代理體現了一個類的單一職能原則,就是一個類只作本身的功能,不摻雜其餘東西,這樣這個類被修改的概率纔會最小。
職責清晰:真實的角色就是現實實際的業務邏輯,不用關係其餘非本職的東西,經過後期的代理完成一件事務,附帶的結果就是變成簡潔清晰
高擴展性:具體主題角色是隨時發生變化的,只要它實現了接口,因此它不管怎麼變化,都逃不脫如來佛的手掌(接口)的控制,那咱們的代理類徹底能夠在不作任何修改的狀況下使用。
智能化:在動態代理中能夠體現出具體的智能化,關於動態代理在下一節中進行講解。
強制代理是代理模式的一種延伸,代理模式是經過代理找到實際的角色動做,可是強制代理要求經過實際角色得到代理,否則不讓訪問。在現實中體現就是,房主和房屋代理簽定了合同,若是有房客想要租這個房就只能找這個固定的房屋代理,不能找其餘的。不論是new出來一個房屋代理也好,仍是直接找房主也好,都是租不了房的。
強制代理接口以下,只是增長了一個getProxy()
方法,得到指定的代理:
interface Homeowner{ public void LeaseHouse(Home home); public Homeowner getProxy(); }
實現類也做了一些的修改,先看房主角色
class RealHomeowner implements Homeowner{ private Homeowner proxy; @Override public void LeaseHouse(Home home) { if (isProxy()){ System.out.println("房價是 "+ home.price); System.out.println("房子顏色是 "+ home.color); }else { System.out.println("請找房屋代理"); } } // 得到本身的代理 @Override public Homeowner getProxy() { this.proxy=new HomeProxy(this); return this.proxy; } // 校驗是不是代理訪問 private Boolean isProxy(){ if (this.proxy == null){ return false; }else { return true; } } }
強制代理的代理類
class HomeProxy implements Homeowner{ private Homeowner homeowner; public HomeProxy(Homeowner homeowner){ this.homeowner = homeowner; } @Override public void LeaseHouse(Home home) { System.out.println("裝修房子"); home.color="red"; System.out.println("提高價格"); home.price=home.price+1000; homeowner.LeaseHouse(home); } // 由於代理上面沒有代理就返回本身 @Override public Homeowner getProxy() { return this; } }
若是此時代理又被代理了,能夠繼續延伸下去。
此時若是按照正常的代理模式進行訪問的話,
public static void main(String[] args) { RealHomeowner realHomeowner=new RealHomeowner(); Home home=new Home(1000,"red"); realHomeowner.LeaseHouse(home); HomeProxy homeProxy = new HomeProxy(realHomeowner); homeProxy.LeaseHouse(home); }
發如今進行出租房子的時候,進行了拒絕出租。這個代理對象是你new出來的,因此真是對象固然不認,這就比如你和A代理公司簽定了合同,可是房客去B代理公司租你的房子,確定是不行的。
裝修房子 提高價格 請找房屋代理
此時若是更改爲以下:
public static void main(String[] args) { RealHomeowner realHomeowner=new RealHomeowner(); Home home=new Home(1000,"red"); Homeowner homeProxy = realHomeowner.getProxy(); homeProxy.LeaseHouse(home); }
就會發現房子被租出去了
裝修房子 提高價格 房價是 2000 房子顏色是 red
強制代理的概念就是要從真是對象查找代理角色,不容許直接訪問真實角色
一個類能夠實現多個接口,完成不一樣的任務的整合,也就說代理類不只能夠實現主題接口,也能夠實現其餘接口完成不一樣的任務,並且代理的目的就是在目標對象方法的基礎上做加強,這種增長本質上就是對目標對象的方法進行攔截過濾。好比如今房屋中介不想本身進行裝修房子了,因而把裝修單獨拆出來做爲一個接口,在內部進行實現。
interface RenovationInterface{ public void Renovation(Home home,String color); }
代理類
class HomeProxy implements Homeowner , RenovationInterface{ private Homeowner homeowner; public HomeProxy (Homeowner homeowner){ this.homeowner = homeowner; } @Override public void LeaseHouse(Home home) { System.out.println("裝修房子"); this.Renovation(home,"red"); System.out.println("提高價格"); home.price=home.price+1000; homeowner.LeaseHouse(home); } @Override public Homeowner getProxy() { return this; } @Override public void Renovation(Home home, String color) { home.color = color; } }
一個代理類能夠代理多個真實的角色,而且真實角色之間能夠有耦合關係,能夠自行的進行擴展。