什么时候使用代理?
在对已有的方法进行使用的时候,需要对原有的方法进行改进或者修改的时候,这时候有两种改进选择:修改原有的方法来适应选择的使用方式,或者使用一个第三者方法来调用原有的方法并对方法产生的结果进行一定的控制。修改原有的方法违背了“对扩展开放,对修改封闭的原则”(开放封闭原则)而且在原来方法中作修改可能使得原来累的功能变得模糊和多元化,而使用第二种方式可以将功能划分的更加清晰,有助于后面的维护。所以第二种方式是一个比较好的选择。
java与模式将代理分为8种:
1、远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。可以将一个在世界某个角落一台机器通感代理家乡或局域网中的部分。
2、虚拟(Virtual)代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。
3、Copy-on-write代理:虚拟代理的一种,把复制(克隆)拖延到只有在客户端需要时才真正采取行动。
4、保护(Protected or Access)代理:控制一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。
5、Cache代理:为某一个目标操作的结果提供临时存储空间,以便多个客户端可以共享这些结果。
6、防火墙(Firewall)代理:保护目标,不让恶意用户接近。
7、同步(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
8、只能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,比如将对此对象的调用次数纪录下来等.
代理模式涉及角色:
1、抽象主题角色:声明了真实主题和代理主题的共同接口,这样一来任何使用真实主题的地方都可以使用代理主题。
2、代理主题(Proxy)角色:代理主题角色内部含有对真实主题的引用,从而可以在任何时候操作真实主题对象,代理主题角色提供一个与真实主题角色相同的接口,以便可以在任何时候可以替代真实主体;控制对真实主题的引用,负责在需要的时候创建和删除真实对象;代理角色通常在将客户端调用真实主题之前或者之后都要执行某个操作,而不是大司农春的将调用传递给真实主题对象。
3、真实主题角色:定义了代理角色所代表的真实对象。
例:
有一个装字符串的容器对象,包含添加addItem和removeItem方法,要在添加之前判断被添加的字符串是否合法,如果是非法字符则不允许添加,如果是不雅观的字符则替换成其他字符再添加到容器中.
容器接口:
/** * 容器 * @version Jan 5, 2011 10:28:14 PM * @author _an. * */ public interface Container { /** * 添加项 */ public void addItem(String item); /** * 删除项 * @param item */ public void remove(String item); public String getContent(); }
容器:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 真实的容器对象 * @version Jan 5, 2011 10:30:15 PM * @author _an. * */ public class RealContainer implements Container { /** * 存放数据集合 */ List
代理的handler:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * * @version Jan 5, 2011 10:34:42 PM * @author _an. * */ public class ContainerInvokHandler implements InvocationHandler { // 被代理的对象 private Object continer; // 过滤器 private Filter filter; // 设置被代理对象 public ContainerInvokHandler(Object continer, Filter filter) { this.continer = continer; this.filter = filter; } /** * 绑定代理对象将要执行的代码 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 调用后的返回值 Object result = null; if(filter.doFilter(method, args)){ System.out.println("proxy invoke is ok."); result = method.invoke(continer, args); System.out.println(result); }else{ System.out.println("proxy invoke is fail."); } return result; } }
处理字符串的过滤器(责任链模式)
import java.lang.reflect.Method; /** * 过滤器 * @version Jan 5, 2011 10:46:29 PM * @author _an. * */ public interface Filter { /** * 过滤 * @param o * @return */ public boolean doFilter(Method method, Object[] params); }
非法内容过滤:
import java.lang.reflect.Method; public class ContentCheckFielter implements Filter { public boolean doFilter(Method method, Object[] params) { if(!"addItem".equals(method.getName())){ return true; } String content = (String)params[0]; System.out.println("add an item '" + content + "' to continer."); if("AV av 苍井空 小泽玛利亚".indexOf(content) != -1){ System.out.println(content+" is fail value."); return false; } return true; } }
不雅观字符过滤:
import java.lang.reflect.Method; public class StringContentFilter implements Filter { public boolean doFilter(Method method, Object[] params) { if(!"addItem".equals(method.getName())){ return true; } String content = (String)params[0]; System.out.println("add an item '" + content + "' to continer."); if("proxychain".equals(content)){ params[0] = "PC is simple."; } return true; } }
责任链接口:
/** * 过滤器链 * @version Jan 5, 2011 11:05:26 PM * @author _an. * */ public interface FilterChain extends Filter { /** * 添加过滤器 * @param filter */ public FilterChain addFilter(Filter filter); /** * 删除过滤器 * @param filter */ public FilterChain removeFilter(Filter filter); }
链实现类:
import java.lang.reflect.Method; import java.util.Vector; public class ProxyFilterChain implements FilterChain { private Vector
代理对象生成工厂:
import java.lang.reflect.Proxy; public class ContainerFacroty { public static Container getContinerInstance(){ // 真实对象 RealContainer real = new RealContainer(); // 过滤器 FilterChain chain = new ProxyFilterChain(); // 添加过滤器 chain.addFilter(new ContentCheckFielter()).addFilter(new StringContentFilter()); // 代理回执 ContainerInvokHandler handler = new ContainerInvokHandler(real, chain); return (Container) Proxy.newProxyInstance(ContainerFacroty.class.getClassLoader(), real.getClass().getInterfaces(), handler); } }
客户端:
public class Client { public static void main(String[] args) { Container continer = ContainerFacroty.getContinerInstance(); continer.addItem("proxychain"); continer.addItem("AV"); continer.addItem("爱上了的看法就"); continer.addItem("苍井空"); System.out.println(continer.getContent()); } }