代理模式定义
代理模式(Proxy Pattern)为另一个对象提供一个替身或占位符以控制对这个对象的访问。
在一些情况下,客户端不想或不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介作用,去掉客户不能看到的内容和服务或者增添客户需要的额外服务。
最常见的代理模式有以下三种:
远程代理:为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以在同一台主机中,也可以在另一台主机中。远程代理又称为大使(Ambassador)。
虚拟代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象,真实对象只在需要时才会被真正创建。
保护代理:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
代理模式能够协调调用者和被调用者,能够在一定程度上降低系统的耦合度。
代理模式结构图
图中:
Subject表示抽象主题角色,它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题;
Proxy表示代理主题角色,代理主题角色内部含有对真实主题的引用,从而可以再任何时候操作真是主题对象,它可以控制真实主题的应用;
RealSubject表示真实主题角色,它定义了代理角色所代表的真实对象。
代理模式实例——日志记录代理
实例说明
在某应用软件中需要记录业务方法的调用日志,在不修改现有业务类的基础上为每一个类提供一个日志记录代理类,在代理类中输出日志,如在业务方法method()调用之前输出“方法method()被调用,调用时间为2010-10-10 10:10:10”,调用之后如果没有抛异常则输出“方法method()调用成功”,否则输出“方法method()调用失败”。在代理类中调用真实业务类的业务方法,使用代理模式设计该日志记录模块的结构,绘制类图并编程模拟实现。
实例类图
实例类图中与代理模式结构图对应的类主要有:
AbstractLog接口充当抽象主题;
LoggerProxy类充当代理主题;
BusinessClass类充当真实主题。
实例代码
AbstractLog.java:
//抽象日志记录类:抽象主题 |
LoggerProxy.java:
import java.util.*; |
BusinessClass.java:
//业务类:真实主题 |
Client.java:
//客户端测试类 |
运行结果
附加描述
在本实例中,通过代理类LoggerProxy来间接调用真实业务类BusinessClass的方法,可以在调用真实业务方法时增加新功能(如日志记录),此处使用的是代理模式的一种较为简单的形式,类似于保护代理,在实施真实调用时可以执行一些额外的操作。由于代理主题和真实主题实现了相同的接口,因此在客户端可以针对抽象编程,而将具体代理类类名存储至配置文件中,增加和更换代理类和真实类都很方便,无需修改源代码,满足开闭原则。
后话
之前对代理一知半解,这次趁着学习代理模式也对代理更有所认知了。
代理的英文有好多个,agent、proxy、stub和surrogate是比较常见到的几个英文。