一.类图
二.意图
为其他对象提供一种代理以控制对这个对象的访问。
三.适用性
a) 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy 模式。下面是一 些可以使用Proxy 模式常见情况:
1. 远程代理(Remote Proxy )为一个对象在不同的地址空间提供局部代表。2. 虚代理(Virtual Proxy )根据需要创建开销很大的对象。在动机一节描述的ImageProxy 就是这样一种代理的例子。3. 保护代理(Protection Proxy )控制对原始对象的访问。保护代理用于对象应该有不同 的访问权限的时候。4. 智能指引(Smart Reference )取代了简单的指针,它在访问对象时执行一些附加操作。b) 它的典型用途包括:
i. 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它
ii. 当第一次引用一个持久对象时,将它装入内存。
iii. 在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
四.实例
考研代理本来是我最讨厌的一类人之一,但是今天不得不拿这个例子出来讲一下。对于要考研的人来说,考研代理无疑为他们提供了方便,只要在他这里报名交钱就行了,其他的事情由他为自己安排。
package explore.proxy; public interface TrainOrgnization { public void register(); } package explore.proxy; public class LingHangOrgnization implements TrainOrgnization { @Override public void register() { System.out.println("欢迎报名领航,祝您考试成功!!"); } } package explore.proxy; public class HaiTianOrgnization implements TrainOrgnization { @Override public void register() { System.out.println("欢迎报名海天,祝您考试成功!"); } } package explore.proxy; public class StudentProxy { protected TrainOrgnization orgz; public StudentProxy(TrainOrgnization orgz) { this.orgz = orgz; } } package explore.proxy; import java.util.Random; public class StuentOfLingHangProxy extends StudentProxy implements TrainOrgnization { public StuentOfLingHangProxy(LingHangOrgnization orgz) { super(orgz); } //选取座位号 public void chooseSeatNum() { System.out.println("您的座位号:" + Math.abs(new Random().nextInt())); } //打印收据 public void printCheck() { System.out.println("您的收据"); } @Override public void register() { printCheck(); chooseSeatNum(); orgz.register(); } } package explore.proxy; import java.util.Random; public class StuentOfHaiTianProxy extends StudentProxy implements TrainOrgnization { public StuentOfHaiTianProxy(HaiTianOrgnization org) { super(org); } // 选取座位号 public void chooseSeatNum() { System.out.println("您的座位号:" + Math.abs(new Random().nextInt())); } // 打印收据 public void printCheck() { System.out.println("您的收据"); } @Override public void register() { printCheck(); chooseSeatNum(); orgz.register(); } } package explore.proxy; public class Client { public static void main(String[] args) { StuentOfLingHangProxy lhProxy = new StuentOfLingHangProxy(new LingHangOrgnization()); StuentOfHaiTianProxy htProxy = new StuentOfHaiTianProxy(new HaiTianOrgnization()); //报名领航 lhProxy.register(); //报名海天 htProxy.register(); } }
上面展示的是静态代理的形式,每一个类对应一个代理类,这样实现起来可能比较麻烦。所以JDK同时提供了动态代理的实现具体的类是InvocationHandler和Proxy。
相对于上面的例子两个考研机构不变,但是多了一个代理工厂控制类,动态生成代理类:
package explore.dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class ProxyFactory implements InvocationHandler { private TrainOrgnization proxied; public ProxyFactory(TrainOrgnization proxied) { this.proxied = proxied; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("代理类: " + proxy.getClass() + ", method: " + method); return method.invoke(proxied, args); } } package explore.dynamicproxy; import java.lang.reflect.Proxy; import java.util.Random; public class Client { // 选取座位号 public void chooseSeatNum() { System.out.println("您的座位号:" + Math.abs(new Random().nextInt())); } // 打印收据 public void printCheck() { System.out.println("您的收据"); } public void register(TrainOrgnization orgz) { chooseSeatNum(); printCheck(); orgz.register(); } public static void main(String[] args) { HaiTianOrgnization real = new HaiTianOrgnization(); TrainOrgnization proxy = (TrainOrgnization) Proxy.newProxyInstance( TrainOrgnization.class.getClassLoader(), new Class[] { TrainOrgnization.class }, new ProxyFactory(real)); new Client().register(proxy); } }