本文是在學習中的總結,歡迎轉載但請注明出處:http://blog.csdn.net/pistolove/article/details/51550035
代理模式為另外一個對象提供替身或占位符以控制對這個對象的訪問。使用代理模式創建代表對象,讓代表對象控制某對象的訪問,被代理的對象可以是遠程的對象、創建開消大的對象或需要安全控制的對象。(摘自Head First 中文版第460頁)
代理模式中,代理類(proxy class)對它的客戶隱藏了對象的具體信息。因此,在使用代理模式時,常常會在代理類中創建對象的實例;其主要在不改變接口的條件下,來“控制”對象的訪問,“控制”占主導地位。相比于裝潢者模式,裝潢者模式將目標對象傳入裝潢類中,其主要是“擴大”功能。
大多數情況下,代理類和被代理對象是has-a關系(組合),除非代理類直接繼承被代理類構成is-a關系(繼承)。經常使用代理分為靜態代理和動態代理。靜態代理在隨著時間的推移會出現問題,主要表現在如果類方法數量愈來愈多的時候,代理類的代碼量是10分龐大的。其實在程序運行前就已存在代理類的字節碼文件,代理類和被代理類的關系在運行前就已肯定了。
動態代理則不會出現上面所述的問題。在動態代理中,動態代理類的源碼是在程序運行期間由JVM根據反射等機制動態的生成,所以不存在代理類的字節碼文件。代理類和被代理類的關系是在程序運行時肯定。 Spring AOP可以算作是代理模式的1個典型利用,通過參數便可判斷真實類,而無需事前實例化,這樣可以實現解耦和代碼靈活多變。
抽象角色:聲明共同接口。這樣,在任何可使用目標對象的地方都可使用代理對象。
代理角色:代理對象包括對目標對象的援用,在任什么時候候可操作目標對象;代理對象提供1個與目標對象相同的接口,以即可以在任什么時候候替換目標對象。
真實角色:代理對象所代表的目標對象,代理角色所代表的真實對象,其是終究要援用的對象。
靜態代理代碼示例以下所示:
package headfirst.design.proxy;
public interface Itraget {
public void say();
}
package headfirst.design.proxy;
public class TargetObject implements Itraget {
@Override
public void say() {
System.err.println("I want to say something");
}
}
package headfirst.design.proxy;
public class PorxyObject implements Itraget{
private Itraget target;
PorxyObject() {
this.target = new TargetObject();
}
@Override
public void say() {
this.target.say();
}
}
package headfirst.design.proxy;
public class Test {
public static void main(String[] args) {
Itraget pItraget = new PorxyObject();
pItraget.say();
}
}
動態代理代碼示例以下所示:
package headfirst.design.JDKproxy;
public interface ITarget {
public void update();
}
package headfirst.design.JDKproxy;
public class ConcreateTarget implements ITarget {
@Override
public void update() {
System.err.println("I am jdk proxy");
}
}
package headfirst.design.JDKproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class PorxyHandle implements InvocationHandler {
private Object target;
public Object bind(Object obj) {
target = obj;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object obj = null;
obj = method.invoke(target, args);
return obj;
}
}
package headfirst.design.JDKproxy;
public class Test {
public static void main(String[] args) {
PorxyHandle handle = new PorxyHandle();
ITarget tItraget = (ITarget) handle.bind(new ConcreateTarget());
tItraget.update();
}
}
Java RMI(遠程接口調用)中的stub對象就是代理對象,客戶必須獲得了stub對象才能給你調用其中的方法(具體情況不在此講授感興趣可以看看源碼)。java.lang.reflect.Proxy也使用了代理模式,可以去看看源碼學習學習。
動態代理的優點:動態代理類比較簡潔,避免了創建多個不同靜態代理的麻煩和重復過剩的代碼。調用目標代碼時,在方法“運行時”動態的加入,更加靈活。
動態代理的缺點:系統變得靈活了,但是效力有所下降,其比靜態代理慢1點。代碼的可讀性不好,不太容易理解。只能對實現了接口的類進行代理。
本文只是簡單介紹了代理模式,并未對其進行深入探討,略顯粗糙。希望本文對你有所幫助。
上一篇 網絡與通信:網絡其他問題
下一篇 [置頂] 微信開發__入門