设计模式之代理模式

来源:互联网 发布:常见的网络促销方式 编辑:程序博客网 时间:2024/06/10 16:58
代理模式是一种常用的设计模式,首先看一下代理模式的定义:代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。
使用代理模式创建代表对象,让代表对象控制某对象的访问,被代理的对象可以是远程的对象,创建开销大的对象和需要安全控制的对象。
代理模式的类图如下:

可以看到,代理模式的类图还是比较简单的,定义一个Subject接口,Proxy类和RealSubject类都实现这个接口,这样Proxy类就可以完全代替RealSubject类了。Proxy持有RealSubject的引用。在某些例子中,Proxy还会负责RealSubject对象的创建和销毁。客户和RealSubject的交互都必须通过Proxy。因为Proxy和RealSubject实现相同的接口Subject,所以任何用到RealSubject的地方,都可以用Proxy取代。Proxy也控制了对RealSubject的访问,在某些情况下,我们可能需要这样的控制。这些情况包括RealSubject是远程的对象,RealSubject创建开销大,或RealSubject需要被保护
下面来看一下代理的这三个应用场景
一.远程代理
远程代理就好比"远程对象的本地代表"。何谓"远程对象"?这是一种对象,活在不同的Java虚拟机堆中(更一般的说法为,在不同的地址空间运行的远程对象)。何谓"本地代表"?这是一种可以由本地方法调用的对象,其行为会转发到远程对象中。远程代理可以作为另一个JVM上对象的本地代表。调用代理的方法,会被代理利用网络转发到远程执行,并且结果会通过网络返回给代理,再由代理将结果转给客户。
二.虚拟代理
虚拟代理作为创建开销大的对象的代表。虚拟代理经常直到我们真正需要一个对象的时候才创建它。当对象在创建前和创建中时,由虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。
举个例子,我们要在应用程序上展示CD封面的图,限于连接带宽和网络负载,下载图片可能需要一些时间,所以在等待图像加载的时候,应该显示一些东西,一旦图像被加载完成,刚才显示的东西就会消失,展示图像。想做到这样,简单的方式就是利用虚拟代理。虚拟代理可以代理Icon,管理背景的加载,并在加载未完成时显示"图像加载中,请稍后",一旦加载完成,展示图像。
三.保护代理
保护代理主要是控制真实对象访问的权限,比如说有一个对象配对的功能,我们有一个Person的实体,Person有两个属性,兴趣和分值,其中兴趣是只能由自己来更改,分值只能由别人来更改,要不然我的兴趣被别人更改了,或者我自己改了我的分值,系统就乱套了。所以这两个属性就可以用保护代理来保护修改的权限。

上面介绍的代理类图是所谓的静态代理, 所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。 
静态代理类优缺点 
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。 
缺点: 
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。 
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。 
有了静态代理的概念,就会有动态代理, 动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。 动态代理之所以被称为动态,是因为运行时才将它的类创建出来
鼎鼎大名的Spring AOP就是通过动态代理来实现的,我们知道Spring AOP主要就是面向切面编程,可以动态的可插拔式的加入一些通用逻辑,如日志的收集,性能统计,安全控制,事务处理等功能。
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强。