三十八:代理模式
一:什么是代理
代理模式给某一个对象提供一个代理对象,并由代理对象控制原对象的引用.
中国人是一个含蓄的民族,讲求微妙和间接的交流方式,对象间的间接通信也同样是面向对象的设计中一条重要的"审美观"。间接性的通信可以给出较低的耦合关系,较强的合作关系,以及微妙的结构和易于复用的设计架构。
代理模式的英文叫做Proxy,所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动,在一些情况下,一个客户不想或者不能直接引用一个对象,而代理对象可以在客户和目标之间起到中介的作用.
比如说Window的快捷方式(Shortcut)就是一个代理的例子,如果原对象被删除,则快捷方式虽然可以存在,但是在调用时会给出错误.
二:代理的种类
如果按使用的目的来划分,代理有以下几种:
(A)远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象,这个不同的地址空间可以是在本机器中,也可是在另一台机器中,远程代理又叫大使.
(B)虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建.
(C)保护(Protect)代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限.
(D)智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来.
.....上面是最常用的代理,还有其他的种类,在此不作介绍.
三:代理模式的角色
(A)抽象主题角色:声明了真实主题和代理主题的共同接口,这样一来在任何可以使用真实主题的地方都可以使用代理主题。
(B)代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象:代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候都可以替代真实主体,控制对真实主题的引用,负责在需要的时候创建真实主题对象(和删除真实主题对象);代理角色通常在将客户端调用传递给真实的主题之前或者之后,都要执行某个操作,而不是单纯地将调用传递给真实主题对象.
(C)真实主题角色:定义了代理角色所代理的真实对象.
下面是示意性的源码:
package cai.milenfan.basic.test; //抽象主题角色abstract public class Subject { //申明一个抽象的请求方法abstract public void request(); } package cai.milenfan.basic.test; //具体主题角色public class RealSubject extends Subject{ public void request() { System.out.println("request from RealSubject........"); } } package cai.milenfan.basic.test; public class ProxySubject extends Subject{ private RealSubject realSubject; //请求前的操作private void preRequest(){ //do something you want before the request... } public void request() { preRequest(); if(realSubject==null){ realSubject = new RealSubject(); } realSubject.request(); postRequest(); } private void postRequest(){ //do something you want after the request } } package cai.milenfan.basic.test; //客户端调用. public class TestProxy { public static void main(String[] args){ Subject subject = new ProxySubject(); subject.request(); } } package cai.milenfan.basic.test; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List; import java.util.Vector; public class VectorProxy implements InvocationHandler{ private Object proxyobj; public VectorProxy(Object obj){ proxyobj = obj; } //静态工厂方法public static Object factory(Object obj){ Class cls = obj.getClass(); return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new VectorProxy(obj)); } //调用某个方法public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { System.out.println("before calling " method); if(args!=null){ for(int i=0;i<args.length;i ){ System.out.println(args[i] ""); } } Object o = method.invoke(proxyobj, args); System.out.println("after calling " method); return o; } public static void main(String[] args){ List v = null; v = (List)factory(new Vector()); v.add("Milenfan"); v.add("czy"); } }