代理模式
1.定義
為其他物件提供一種代理以控制對這個物件的直接控制

UML建模圖.png
2.使用場景:
當無法或者直接訪問到目標物件的時候,或者訪問某個物件有困難的時候,可以通過一個代理物件來間接訪問,為了保證客戶端使用的透明性,委託物件與代理物件要實現相同的介面,即(代理和委託的約束)
3.代理模式分類
分為兩種:靜態代理、動態代理。靜態代理是由程式設計師建立或特定工具自動生成原始碼,在對其編譯。在程式設計師執行之前,代理類.class檔案就已經被建立了。動態代理是在程式執行時通過反射機制動態建立的
3.1 靜態代理模式
- 簡單實現
/** * 介面約束 */ public abstract class Subject { //普通的業務方法 abstract void visit(); }
- 委託類
/** * 業務真實處理類 */ public class RealSubject extends Subject { @Override void visit() { System.out.println("真正的實現方法"); } }
- 代理類
/** * 代理類 */ public class ProxySubject extends Subject { privateSubject mSubject; public ProxySubject(Subject subject) { this.mSubject=subject; } @Override void visit() { mSubject.visit(); } }
-
專案中使用示例
以Android工程示例,在專案開發中,前期使用的網路訪問請求框架為volley,但是在專案迭代幾個版本以後,發現使用volley框架,對大檔案的下載支援不是很好(因為volley在下載檔案的時候,目標檔案有多大,直接建立一個和目標檔案一樣大小的檔案,佔用資源較大)這個時候,要求更換網路請求框架,如果這個時候,程式碼耦合度高的話,則使用到網路請求的地方,都會進行相應的修改,當然一個好的架構,會讓切換框架變的非常簡單。如下
public interface Ihttp { /** * GET 請求 * @param url */ void get(String url); /** * POST 請求 * @param url * @param params */ void post(String url,String params); //.... }
代理請求網路類
public class HttpProxy implements Ihttp { private void HttpProxy() {} public static HttpProxy mInstance; public static HttpProxy getInstance() { if (mInstance == null) { synchronized (HttpProxy.class) { if (mInstance == null) mInstance = new HttpProxy(); } } return mInstance; } private Ihttp mModle; public void setHttpModle(Ihttp modle) { this.mModle = modle; } @Override public void get(String url) { mModle.get(url); } @Override public void post(String url, String params) { mModle.post(url, params); } }
okhttp訪問網路框架
public class OkhttpModle implements Ihttp { @Override public void get(String url) { //模擬okhttp請求網路 System.out.println("Okhttp request get()" + url); } @Override public void post(String url, String params) { System.out.println("Okhttp request post(params)" + url); } }
volley訪問網路框架
public class VolleyModle implements Ihttp { @Override public void get(String url) { //模擬Volley請求網路 System.out.println("Volley request get()" +url); } @Override public void post(String url, String params) { System.out.println("Volley request post(params)" +url); } }
專案初始化配置使用
public class Client { public static void main(String[] args){ //如果使用volley請求框架 //HttpProxy.getInstance().setHttpModle(new VolleyModle()); //如果使用okhttp請求框架 HttpProxy.getInstance().setHttpModle(new OkhttpModle()); HttpProxy.getInstance().get("http://www.baidu.com"); } }
列印結果:
Okhttp request get()http://www.baidu.com
4.1 動態代理模式
定義:通過反射機制動態生成代理者物件,也就是說在code階段不知道要代理誰,在執行階段決定,java也提供了一個便捷的動態代理介面
/** * 介面約束 */ public interface Subject { //普通的業務方法 void visit(); }
/** * 業務真實處理類 */ public class RealSubject implements Subject { @Override public void visit() { System.out.println("真正的實現方法"); } }
public class DynamicProxy implements InvocationHandler { private Object obj; public DynamicProxy(Object obj) { this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object invoke = method.invoke(obj, args); return invoke; } }
public class Client { public static void main(String[] args){ Subject subject=new RealSubject(); DynamicProxy proxy = new DynamicProxy(subject); ClassLoader classLoader = subject.getClass().getClassLoader(); Subject real = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, proxy); real.visit(); } }