代理模式的本質是一個中間件,主要目的是解耦合服務提供者和使用者。使用者通過代理間接的訪問服務提供者,便於后者的封裝和控制。是一種結構性模式。
1.目的
為外部調用者提供一個訪問服務提供者的代理對象。
2.動機
限制對目標對象的直接訪問,降低耦合度。
3.優缺點
優點:
- 低耦合
- 易擴展
- 靈活度高
缺點:
- 間接訪問可能會延遲請求相應
- 增加工作量
4.分類
- 靜態代理
- 動態代理
代理類本身的實現可能並不簡單,加上每一個需要代理的對象均均需要實現一個代理類,其工作量本身比較大,易出錯。
所謂動態代理(DynamicProxy)是指在程序運行時動態的生成對目標對象的訪問接口。
本文主要介紹前者,關於后者可以參考JDK自帶的動態代理。
5.主要用途
代理模式在以下場景比較適用:
1、遠程代理。 2、虛代理。 3、保護代理。4、智能指引代理。5、寫時復制(Copy-on-Write)代理。 6、緩存代理。 7、防火牆代理。 8、同步化代理。
6.原理
下面是GoF介紹典型的代理模式UML類圖

Subject:
定義RealSubject對外的接口,且這些接口必須被Proxy實現,這樣外部調用proxy的接口最終都被轉化為對realsubject的調用。
RealSubject:
真正的目標對象。
Proxy:
目標對象的代理,負責控制和管理目標對象,並間接地傳遞外部對目標對象的訪問。
- Remote Proxy: 對本地的請求以及參數進行序列化,向遠程對象發送請求,並對響應結果進行反序列化,將最終結果反饋給調用者;
- Virtual Proxy: 當目標對象的創建開銷比較大的時候,可以使用延遲或者異步的方式創建目標對象;
- Protection Proxy: 細化對目標對象訪問權限的控制;
7.實現
下面我們使用兩個例子來實際體驗一下代理模式的應用
網絡代理
對於一些國內不能直接訪問的網站,合法的使用的網絡代理可以實現對目標網站的訪問;

定義公共接口類Server:
public interface Server{ void visit(String url); }
代理服務器ProxyServer:
public class ProxyServer implements Server{ private RealServer realServer; public ProxyServer(String serverName){ this.realServer = new RealServer(serverName); } @Override public void visit(String url) { realServer.visit(url); } }
目標服務器RealServer:
public class RealServer implements Server { private String serverName; public RealServer(String serverName) { this.serverName = serverName; System.out.println("This is " + serverName); } @Override public void visit(String url) { response(url); } private void response(String res) { System.out.println("This is response of " + res + " from server:" + serverName); } }
演示:
public class Demo { public static void main(String[] args) { Server server = new ProxyServer("www.google.com"); server.visit("map.google.com"); } }
智能指針引用計數
下面使用代理模式簡單的模擬指針引用計數問題
接口類Obj:
public interface Obj{ void GetAttr(); Obj copy(); void delete(); }
智能指針類SmartPointer:
public class SmartPointer implements Obj{ private RealObj realObj; private int counter = 1; public SmartPointer(String objType){ this.realObj = new RealObj(objType); } @Override public void GetAttr() { if(counter > 0) { realObj.GetAttr(); } System.out.println("Smart Ref: " + counter); } public Obj copy() { if(counter > 0) { counter += 1; return this; } System.out.println("Invalid Pointer!"); return null; } public void delete() { if(counter > 0) { counter -= 1; if(0 == counter) { realObj = null; } } else { System.out.println("Invalid Pointer!"); } } }
被引用對象類RealObj:
public class RealObj implements Obj { private String objType; public RealObj(String objType) { this.objType = objType; System.out.println("Create Obj: " + objType); } @Override public void GetAttr() { System.out.println("get attr of real obj " + objType); } @Override public Obj copy() { // TODO Auto-generated method stub return null; } @Override public void delete() { // TODO Auto-generated method stub } }
參考:
GoF《Design Patterns: Elements of Reusable Object-Oriented Software》
https://www.runoob.com/design-pattern/proxy-pattern.html
