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