代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。
张老板是一个生意人,由于经营小本生意。为了降低层本,没有雇佣太多的人,很多事情都必须事必躬亲,如订机票、酒店。此时:
机票/酒店提供商:提供飞机票订购服务和酒店订购服务。
张老板(客户端):张老板即为客户,张老板需要自己亲自与机票/酒店提供商打交道,订机票和酒店。
过了几天后,张老板经营合理,生意越做越大,经常需要出差,需要订机票、酒店等。由于老板非常忙,因此这些工作需要交给秘书来完成。此时:
机票/酒店提供商:提供飞机票订购服务和酒店订购服务。
秘书(代理角色):为张老板订阅机票、酒店等,不再需要张老板亲自与机票/酒店供应商打交道。
张老板(客户端):张老板从订机票、酒店琐碎的事情中脱离出来,更多精力花费在打理生意上面。
上面就是一个现实版本的代理模式。UML类图如下:


代理模式所涉及的角色有:
抽象主题角色(Subject):声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以使用代理主题。
代理主题(ProxySubject)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象。代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主题;
真实主题(RealSubject)角色:定义了代理角色所代表的真实对象。
Java代码:
// 抽象主题
public abstract class Subject {
public abstract void request();
}
// 真实主题
public class RealSubject extends Subject {
public RealSubject() {
System.out.println("RealSubject()");
}
public void request() {
System.out.println("From real subject.");
}
}
// 代理主题
public class ProxySubject extends Subject {
private RealSubject realSubject;
public ProxySubject() {}
public void request() {
preRequest();
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.request();
postRequest();
}
private void preRequest() {
System.out.println("#### preRequest()");
}
private void postRequest() {
System.out.println("#### postRequest()");
}
}
// 客户端
public class Client {
public static void main(String[] args) {
Subject subject = new ProxySubject();
subject.request();
}
}静态的类图并不适合于反映出模式在运行时的特征,时序图更能够反映出模式的活动情况。下图便是代理模式的时序图,如下:

从上面的时序图可以看出,客户端向代理主题发出请求,代理主题在接到请求的同时,执行了一个preRequest()操作,然后才把请求传递给真实主题。在真实主题将请求返回后,代理主题又执行了一个postRequest()操作,才将控制返回给客户端。