代理模式,個人認為就是把你要使用的一個對象盡享封裝,包裝。編程原對象的一個副本,在使用的時候直接使用他這個副本就可以了!他的作用用專業點的語言描
述就是為其他的對象提供一個代理方便控制這個對象。當我們不能直接調用另外一個對象,但是又不得不用這個對象的某些功能,此時代理對象就能起到鏈接客戶和
目標對象的一個代理.
代理模式一般涉及到三個角色,分別為:
1. 抽象角色:他提供真實對象和代理對象的共同接口。
2. 代理角色:通俗地說,代理角色是對原對象(目標對象)進行包裝,他有著和原對象相同的接口,并且可以執行真實對象的操作。
3. 真實角色:即目標對象,最終我們需要對他的操作。
代理模式分為兩種,一 靜態代理,二 動態代理。
接下來我們介紹一下兩種代理模式:
一 靜態代理
靜態代理即 代理對象和被代理對象在代理之前已經確定好了。他們一起實現相同的接口或者是繼承相同的抽象類。例如:
-
- public abstract class AbsRole{
- abstract public void work();
- }
//定義抽象角色
public abstract class AbsRole{
abstract public void work();
}
-
- public class RealRole extends AbsRole{
- public RealRole(){ }
-
- public void work(){
- System.out.println("調用真實角色中函數!");
- }
- }
//定義真實角色
public class RealRole extends AbsRole{
public RealRole(){ }
public void work(){
System.out.println("調用真實角色中函數!");
}
}
-
- public class ProxyRole extends AbsRole{
- public RealRole real ;
-
- public ProxyRole(){
- }
-
- public void work(){
- this.beforeMethod();
- if(real == null){
- real = new RealRole();
- }
- real.work();
- this.endMethod();
- }
-
- public void beforeMethod(){
- System.out.println("代理前執行函數->beforeMethod()");
- }
-
- public void endMethod(){
- System.out.println("代理時候后執行函數->endMethod()");
- }
- }
//代理角色
public class ProxyRole extends AbsRole{
public RealRole real ;
public ProxyRole(){
}
public void work(){
this.beforeMethod();
if(real == null){
real = new RealRole();
}
real.work();
this.endMethod();
}
public void beforeMethod(){
System.out.println("代理前執行函數->beforeMethod()");
}
public void endMethod(){
System.out.println("代理時候后執行函數->endMethod()");
}
}
各種角色我們都已經定義好了,我們開始測試一下。
- public class Main(){
- public static void main(String[] args){
- AbsRole ar = new ProxyRole();
- ar.work();
- }
- }
public class Main(){
public static void main(String[] args){
AbsRole ar = new ProxyRole();
ar.work();
}
}
二 動態代理
顧名思義,就是不知道到底那個類需要做代理,在使用的時候,更具情況臨時決定。
java動態代理主要是使用java.lang.reflect包中的兩個類。
1. interface InvocationHandler: 他中定義了一個方法
- public Object invoke(Object obj,Method method,Object[] obs)
public Object invoke(Object obj,Method method,Object[] obs)
其中第一個參數 obj 指的是代理類,method是被代理的方法,obs是指被代理的方法的參數組。此方法由代理類來實現。
2. Proxy:該類為動態代理類,主要包括以下內容:
- protected Proxy(InvocationHandler h);
-
- static Class getProxyClass(ClassLoader loader,Class[] interfaces);
-
- static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h);
protected Proxy(InvocationHandler h);
static Class getProxyClass(ClassLoader loader,Class[] interfaces);
static Object newProxyInstance(ClassLoader loader,Class[]interfaces,InvocationHandler h);
動態代理其實是在運行時生成class,所以,我們必須提供一組interface,然后告訴他class已經實現了這些interface,而且在生成Proxy的時候,必須給他提供一個handler,讓他來接管實際的工作。
現在我們把靜態代理的例子修改一下:
-
- public interface AbsRole{
- public void work();
- }
//定義抽象角色;
public interface AbsRole{
public void work();
}
接下來定義真實角色;
- public class RealRole implements AbsRole{
- public RealRole(){};
-
- public void work(){
- System.out.println("調用真實角色方法:RealRole.work()");
- }
- }
public class RealRole implements AbsRole{
public RealRole(){};
public void work(){
System.out.println("調用真實角色方法:RealRole.work()");
}
}
然后書寫動態代理編碼
- public class DynamicProxyRole implements InvocationHandler{
- private Object sub;
-
- public DynamicProxyRole(){}
-
- public DynamicProxyRole(Object ob){
- this.sub = ob;
- }
-
- public Object invoke(Object proxy, Method method, Object[] obs) throws Throwable{
- method.invke(sub,obs);
- return null;
- }
- }
public class DynamicProxyRole implements InvocationHandler{
private Object sub;
public DynamicProxyRole(){}
public DynamicProxyRole(Object ob){
this.sub = ob;
}
public Object invoke(Object proxy, Method method, Object[] obs) throws Throwable{
method.invke(sub,obs);
return null;
}
}
代理類已經書寫完畢,看看是否能正常運行。
- public class Main{
- public static void main(String[] args){
- RealRole rr = new RealRole();
- InvocationHandler dynamicProxy = new DynamicProxyRole(rr);
- Class<?> cls = rr.getClass();
-
- AbsRole r = (AbsRole)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),DynamicProxyRole);
- r.work();
- }
- }
public class Main{
public static void main(String[] args){
RealRole rr = new RealRole();
InvocationHandler dynamicProxy = new DynamicProxyRole(rr);
Class<?> cls = rr.getClass();
AbsRole r = (AbsRole)Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),DynamicProxyRole);
r.work();
}
}
調試成功,動態代理功能完成。
通過靜態代理和動態代理學習,我們小結一下:
靜態代理需要事先確定代理對象和被代理對象,他們要一起繼承或者是實現相同的抽象類。動態代理可以在使用的時候傳入真實對象,得到代理。動態代理還是主要依靠java本身的語言特性,實現代理,更加方便