代理模式的本质是一个中间件,主要目的是解耦合服务提供者和使用者。使用者通过代理间接的访问服务提供者,便于后者的封装和控制。是一种结构性模式。
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!");
- }
- }
- }
View Code
被引用对象类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
-
- }
- }
View Code
参考:
GoF《Design Patterns: Elements of Reusable Object-Oriented Software》
https://www.runoob.com/design-pattern/proxy-pattern.html