代理模式的本質是一箇中間件,主要目的是解耦合服務提供者和使用者。使用者經過代理間接的訪問服務提供者,便於後者的封裝和控制。是一種結構性模式。html
爲外部調用者提供一個訪問服務提供者的代理對象。緩存
限制對目標對象的直接訪問,下降耦合度。服務器
優勢: 網絡
缺點:異步
代理類自己的實現可能並不簡單,加上每個須要代理的對象均均須要實現一個代理類,其工做量自己比較大,易出錯。ide
所謂動態代理(DynamicProxy)是指在程序運行時動態的生成對目標對象的訪問接口。網站
本文主要介紹前者,關於後者能夠參考JDK自帶的動態代理。this
代理模式在如下場景比較適用:google
一、遠程代理。 二、虛代理。 三、保護代理。四、智能指引代理。五、寫時複製(Copy-on-Write)代理。 六、緩存代理。 七、防火牆代理。 八、同步化代理。url
下面是GoF介紹典型的代理模式UML類圖
Subject:
定義RealSubject對外的接口,且這些接口必須被Proxy實現,這樣外部調用proxy的接口最終都被轉化爲對realsubject的調用。
RealSubject:
真正的目標對象。
Proxy:
目標對象的代理,負責控制和管理目標對象,並間接地傳遞外部對目標對象的訪問。
下面咱們使用兩個例子來實際體驗一下代理模式的應用
網絡代理
對於一些國內不能直接訪問的網站,合法的使用的網絡代理能夠實現對目標網站的訪問;
定義公共接口類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