适用环境:
远程代理:为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可以是在另一台主机中。远程代理又叫做大使(Ambasssador)。RMI(Remote Method Invocation 远程方法调用)、Web Service的实现原理。
虚拟代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
Copy-on-Write代理:它是虚拟代理的一种,把复制操作延迟到只有在客户端真正需要时才执行。
保护代理:控制对一个对象的访问,可以给不同用户提供不同级别的使用权限。
缓冲(Cache)代理:微末一个目标操作的结果提供临时的存储空间,以便于多个客户端可以共享这些结果。
防火墙(FireWall)代理:保护目标不让恶意用户接近。
同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等。
在这些种类的代理中,虚拟代理、远程代理和保护代理是常见的代理模式。不同类型的代理模式有不同的缺点,它们应用于不同的场合。
Spring框架中的AOP技术也是代理模式的应用,在Spring AOP中应用了动态代理(Dynamic Proxy)技术。
现实生活中如婚介所就是所谓的代理结构,当你忙于其他事情没有心思去找对象时,可以去找这样的代理机构来间接的帮你找到。
当直接访问某些对象存在问题时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现同样的接口以保证在任何使用真实对象的地方都可以使用代理主题,客户端只需要针对抽象主题进行编程即可。所谓代理,就是一个人或者一个机构代表另一个人或者另一个结构采取行动。通过引入代理对象来间接访问一个对象,这就是代理模式的模式动机。
模式动机:通过引入一个代理对象来间接访问一个对象。
定义:给某一个对象提供一个代理,并由代理对象控制原对象的引用。
模式结构图:
权限代理代码实现:
客户端:
package com.proxypattern.hing;
public class Client {
public static void main(String[] args) {
//注意,客户端不会出现真正要代理的对象,因为该对象已经在代理类中有实例,这样可以避免要代理对象内部信息的泄露
AbstractPermission proxy = (AbstractPermission)XMLUtil.getBean();
proxy.modifyUserInfo();
proxy.setLevel(1);
proxy.modifyUserInfo();
}
}
抽象权限管理类:
package com.proxypattern.hing;
//抽象权限类
public interface AbstractPermission {
public void modifyUserInfo();
public void viewNote();
public void publishNote();
public void modifyNote();
public void setLevel(int level);
}
真实权限管理类:
package com.proxypattern.hing;
//真正的权限类
public class RealPermission implements AbstractPermission {
@Override
public void modifyUserInfo() {
System.out.println("修改用户信息!");
}
@Override
public void viewNote() {
// TODO Auto-generated method stub
}
@Override
public void publishNote() {
System.out.println("发表新帖");
}
@Override
public void modifyNote() {
System.out.println("修改新帖");
}
@Override
public void setLevel(int level) {
}
}
代理权限管理类:
package com.proxypattern.hing;
//代理的权限类
public class ProxyPermission implements AbstractPermission {
private RealPermission rp = new RealPermission();
private int level = 0;
@Override
public void modifyUserInfo() {
if(level == 0) {
System.out.println("对不起,你没有访问权限");
}else {
rp.modifyUserInfo();
}
}
@Override
public void viewNote() {
rp.viewNote();
}
@Override
public void publishNote() {
rp.publishNote();
}
@Override
public void modifyNote() {
if (level == 0) {
System.out.println("对不起,你没有该权限");
}else {
rp.modifyNote();
}
}
@Override
public void setLevel(int level) {
this.level = level;
}
}
优点:
①代理模式能够协调调用者和被调用者,一定程度上降低了系统的耦合度。
②远程代理使得客户端可以访问在远程机器上的对象,远程及其可能具有更好的计算性能和处理速度,可以快速响应并处理客户端请求。
③虚拟代理通过使用一个小对象来代替一个大对象,从而减少系统资源小号,提高系统运行速度。
④保护代理可以控制对真是对象的使用权限。
缺点:
①由于新增了代理对象,因此有些类型的代理模式可能会造成请求速度的变慢。
②实现代理模式需要额外的工作,而且有些代理模式的实现非常复杂。
总结:代理是将真正的主题角色封装到了代理主题角色中,通过相应控制调用真正的主题角色中的内容,而他们必须实现相同的接口,这样会使得客户端使用具有透明性。值得注意的是,此处已经将真实的主题角色设为了private保证了安全性。
代理模式和装饰模式:看起来这两个模式是有较多相似的地方的,但实际上使用代理模式时,代理对象和真实对象之间的关系通常在编译时就已经确定了(当然也有动态代理在编译时才确定),而装饰者则能够在运行时递归地被构造。