设计模式之代理模式(proxy pattern)
代理模式的本质是一个中间件,主要目的是解耦合服务提供者和使用者。使用者通过代理间接的访问服务提供者,便于后者的封装和控制。是一种结构性模式。
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
上一篇: PHP不重新编译,单独添加模块扩展的方法
下一篇: Photoshop 漂亮的绿色房子图标