這就是一個代理模式,讓王工改需求,需要聯絡李總,李總再把工作安排給王工,最終完成了同樣的目的,但是有個了中間人。
同樣在Java裡的代理模式,也這個道理,客戶端不直接訪問實際的物件,而是通過中間的代理物件來訪問實際物件。
代理模式分為靜態代理和動態代理
靜態代理
代理和被代理物件在代理之前是確定的。都實現了相同的介面或繼承相同的抽象類。舉例:
建立IUser介面
/** * 使用者介面 */ public interface IUser { void login(); }
目標物件User:
/** * 實現使用者登入,目標物件 */ public class User implements IUser { @Override public void login() { System.out.println("使用者登入中....."); } }
代理物件UserProxy
/** * 代理物件 */ public class UserProxy implements IUser { private IUser target; public UserProxy(IUser target) { this.target = target; } @Override public void login() { System.out.println("使用者開始登入"); target.login(); System.out.println("使用者結束登入"); } }
測試Run.java
/** * 測試類 */ public class Run { public static void main(String[] args) { //目標物件 User target = new User(); //代理物件,同時把目標物件傳給代理物件 UserProxy userProxy = new UserProxy(target); userProxy.login(); } }
執行結果:
使用者開始登入
使用者登入中.....
使用者結束登入
總結:
1.靜態代理可以代理實現任意介面的目標物件,通用性強。
2.介面有修改,目標物件和代理物件都要進行修改,增加了維護難度。
3.代理物件對應著一個目標物件,每個目標物件實現了部分介面,如果目標物件很多,那麼靜態代理物件也變得臃腫起來。
為了解決2,3問題,引入動態代理。
動態代理
這裡介紹使用JDK的代理方式,同樣可以代理實現介面的類。
步驟如下:
1.編寫一個目標類的介面。
2.實現介面的目標類。
3.建立一個動態代理類,實現InvocationHandler介面,重寫invoke方法。
舉例:步驟1,2使用靜態代理的IUser介面和User目標類。
建立一個動態代理類:
/** * 動態代理類 */ public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target) { this.target = target; } /** * proxy 被代理的物件 * method 被代理物件的方法 * args 方法的引數 * return Object方法的返回值 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("開始登入"); //執行目標類方法 Object result = method.invoke(target, args); System.out.println("結束登入"); return result; } }
測試類:Run2.java
/** * 測試類 */ public class Run2 { public static void main(String[] args) { //目標物件 User target = new User(); //代理物件,同時把目標物件傳給代理物件 DynamicProxy dynamicProxy = new DynamicProxy(target); //給目標生產代理物件 /** * loader 類載入器 * interfaces 實現介面 * h InvocationHandle */ IUser iUser = (IUser) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), dynamicProxy); iUser.login(); } }
執行結果:
使用者開始登入
使用者登入中.....
使用者結束登入