简介
Provide a surrogate or placeholder for another object to control access to it.
为其他对象提供一种代理以控制对这个对象的访问。
代理模式(Proxy Pattern) 也称为 委托模式(Delegate),属于 结构型模式 之一。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
通俗的讲,代理模式 就是我们生活中常见的中介。
优缺点
优点
- 协调调用者和被调用者,降低了系统的耦合度;
- 代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用;
- 职责清晰:真实主题角色 只负责实现实际的业务逻辑,无需关心其他非本职责的事务,通过后期代理的访问控制,可以扩展或缩减实际事务,符合设计模式 单一职责原则,代码简洁清晰;
- 高扩展性:真实主题角色 负责实际业务逻辑,可能经常性变动,但是由于其与 代理类 都实现了 抽象主题,因此,真实主题 的改变不会影响到代理类,符合设计模式 依赖倒置原则,里氏替换原则 和 开闭原则;
- 智能化:主要是基于动态代理的实现,可以在程序运行时生成一个合适的代理类;
缺点
- 由于在客户端和 真实主题 之间增加了 代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢;
- 实现代理模式需要额外的工作(有些代理模式的实现非常复杂),从而增加了系统实现的复杂度;
使用场景
- 当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过也给代理对象来间接访问;
模式讲解
首先看下 代理模式 的通用 UML 类图:
代理模式 一般包含三种角色:
- 抽象主题角色(Subject):抽象主题类 的主要职责是声明 真实主题 与 代理 的共同接口方法,该类可以是接口也可以是抽象类;
- 真实主题角色(RealSubject):该类也被称为 被委托类 或 被代理类,该类定义了代理所表示的真实对象,是负责执行系统真正的逻辑业务对象;
- 代理主题角色(Proxy):也被称为 委托类 或 代理类,其内部持有 RealSubject 的引用,因此具备完全的对 RealSubject 的代理权;
下面是 代理模式 的通用代码展示:
class Client {
public static void main(String[] args) {
ISubject realSubject = new RealSubject();
ISubject proxy = new Proxy(realSubject);
proxy.request();
}
// 抽象主题 Subject
public interface ISubject {
void request();
}
// 真实主题 RealSubject
public static class RealSubject implements ISubject {
@Override
public void request() {
System.out.println("I'm RealSubject.");
}
}
// 代理类 Proxy
public static class Proxy implements ISubject {
private ISubject mRealSubject;
public Proxy(ISubject subject) {
this.mRealSubject = subject;
}
@Override
public void request() {
this.doProxy();
this.mRealSubject.request();
}
private void doProxy() {
System.out.println("代理转发");
}
}
}
代理模式的设计中谨记:代理类(Proxy) 和 真实主题(RealSubject) 都要实现 抽象主题(Subject)接口,这样两者的行为才会一致,并且能够允许多重代理的实现。
注意:从 代理模式 的 UML 类图和通用代码实现上看,代理模式 与 装饰模式 几乎一模一样。代理模式 的 Subject 对应 装饰模式 的 Component,代理模式 的 RealSubject 对应 装饰模式 的 ConcreteComponent,代理模式 的 Proxy 对应 装饰模式 的 Decorator。确实, 从代码实现上看,代理模式 的确与 装饰模式 是一样的(其实 装饰模式 就是 代理模式 的一个特殊应用),但是这两种设计模式所面向的功能扩展面是不一样的:
- 装饰模式 强调 自身功能的扩展。Decorator 所做的就是增强 ConcreteComponent 的功能(也有可能减弱功能),主体对象为 ConcreteComponent,着重类功能的变化;
- 代理模式 强调 对代理过程的控制。Proxy 完全掌握对 RealSubject 的访问控制,因此,Proxy 可以决定对 RealSubject 进行功能扩展,功能缩减甚至功能散失(不调用 RealSubject 方法),主体对象为 Proxy;
简单来讲,假设现在小明想租房,那么势必会有一些事务发生:房源搜索,联系房东谈价格····
假设我们按照 代理模式 进行思考,那么小明只需找到一个房产中介,让他去干房源搜索,联系房东谈价格这些事情,小明只需等待通知然后付点中介费就行了;
而如果采用 装饰模式 进行思考,因为 装饰模式 强调的是 自身功能扩展,也就是说,如果要找房子,小明自身就要增加房源搜索能力扩展,联系房东谈价格能力扩展,通过相应的装饰器,提升自身能力,一个人做满所有的事情。
代理模式 按照代理创建的时期来进行分类的话, 可以分为两种:静态代理、动态代理。具体内容可查看:Java代理模式
总结:代理模式 应用非常广泛,大到一个系统框架,企业平台,小到代码片段,事务处理,都很有可能用到 代理模式。甚至在其他形式的结构型设计模式中,我们都可以看到 代理模式 的影子,有些模式虽然作为单独的一种设计模式,但倒不如说是 代理模式 的一种针对性优化。