代理模式,代理模式java
代理模式就是為某個對象提供一個代理,以控制對這個對象的訪問。代理類負責為委託類預先處理訊息,過濾訊息並轉寄訊息,以及進行訊息被委託類執行後的後續處理。通過代理類這層,能有效控制對委託類對象的直接存取,也能很好的隱藏和保護委託類對象。
代理類和目標類是一模一樣,不允許更改。代理只是控制目標,可以控制讓你訪問還是不讓你訪問。而委託類(業務類)只需要關注商務邏輯本身,保證了委託類(業務類)的重用性。
我們根據代理類的產生時間不同,可以將代理分為靜態代理和動態代理。
(1)靜態代理
所謂的靜態代理就是在運行前就已經知道了代理類和委託類的關係。它由程式員建立或工具組建代理程式類的源碼,再編譯代理類。下面展示一下靜態代理實現代碼:
代理介面:
package static_proxy_package;/** * 代理介面,送禮物 * @author lsh * */public interface Subject {/** * 某個人送禮物 * @param gift */public void giveGift(String name);}委託類:
package static_proxy_package;/** * 委託類,真正要送禮物的人,實現了介面 * @author lsh * */public class RealSubject implements Subject {@Overridepublic void giveGift(String name) {System.out.println(name + "送給了您一份禮物"); }}
代理類:
package static_proxy_package;/** * 代理類,協助委託人送禮物的人,也實現了代理介面 * @author lsh * */public class ProxySubject implements Subject {//代理類持有一個委託類的對象引用private Subject delegate;public ProxySubject(Subject delegate){this.delegate =delegate;}@Overridepublic void giveGift(String name) { System.out.println("送禮物之前");delegate.giveGift(name);System.out.println("送禮物之後");}}
用戶端:
package static_proxy_package;import java.lang.reflect.Proxy;/** * 客戶類 * @author lsh * */public class Client { public static void main(String[] args ){ Subject realSubject = new RealSubject(); Subject proxy =new ProxySubject(realSubject); proxy.giveGift("huazi");}} 利用這種靜態代理,代理對象的一個介面只服務於一種類型的對象,如果要代理的類型很多,勢必要為每一類型都進行代理,靜態代理在程式規模稍大時就無法勝任了。另外,可以想一想如果介面要增加一個方法處理所有實作類別需要實現這個方法外,所有代理類也需要實現此方法,增加代碼的複雜度。
這時我們就可以考慮使用動態代理。Proxy 類是它的父類,這個規則適用於所有由 Proxy 建立的動態代理類。而且該類還實現了其所代理的一組介面,這就是為什麼它能夠被安全地類型轉換到其所代理的某介面的根本原因,這樣可以節省不必要的代碼重複產生,提高了代理類的建立效率。圖示如下:
而且 動態代理最大的好處是介面中聲明的所有方法都被轉移到調用處理器一個集中的方法中處理(InvocationHandler.invoke)。這樣,在介面方法數量比較多的時候,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。下面我們就簡單的來認識一下動態代理。
(2)動態代理:
所謂動態代理就是代理類和委託類的關係是在程式運行時確定的。動態代理類的源碼是在運行期間,由JVM根據反射機制動態產生的,不存在代理類的位元組碼檔案。 下面展示一下動態代理代碼實現:
代理介面:
package static_proxy_package;/** * 代理介面,送禮物 * @author lsh * */public interface Subject {/** * 某個人送禮物 * @param gift */public void giveGift(String name);}
委託類:
package static_proxy_package;/** * 委託類,真正要送禮物的人,實現了介面 * @author lsh * */public class RealSubject implements Subject {@Overridepublic void giveGift(String name) {System.out.println(name + "送給了您一份禮物"); }}
代理類:
package static_proxy_package;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;/** * 採用動態代理調用程式處理類 * @author lsh * */public class proxyHandler implements InvocationHandler {//代理類持有一個委託類的對象引用private Object delegate;public proxyHandler(Object delegate){this.delegate=delegate;}public Subject getInstance(){return (Subject)Proxy.newProxyInstance(delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {Object sub= null;System.out.println("送禮物之前");sub=method.invoke(delegate, args);System.out.println("送禮物之後");return sub;}}
用戶端:
package static_proxy_package;import java.lang.reflect.Proxy;/** * 客戶類 * @author lsh * */public class Client { public static void main(String[] args ){//定義一個委派物件Subject delegate = new RealSubject();//定義一個動態代理類proxyHandler handler = new proxyHandler(delegate);Subject proxy=handler.getInstance();proxy.giveGift("huazi");}}這就是靜態代理和動態代理的簡單介紹。下面做一下靜態代理和動態代理的簡單總結:
對java中動態代理的實現還有諸多疑惑,接下來我會對動態代理的實現原理整理和理解一下。