代理模式: 为其他对象提供一种代理,并以控制对这个对象的访问。而对一个对象进行访问控制的一个原因是为了只有在我们确实需要这个对象时才对它进行创建和初始化。它是给某一个对象提供一个替代者(占位者),使之在client对象和subject对象之间编码更有效率。代理可以提供延迟实例化(lazy instantiation),控制访问, 等等,包括只在调用中传递。 一个处理纯本地资源的代理有时被称作虚拟代理。远程服务的代理常常称为远程代理。强制 控制访问的代理称为保护代理。
常见的代理
1) 远程代理(Remote Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中;
2) 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。 比如打开一个很大的HTML网页时,里面可能有很多的文字和图片,但你还是可以很快的打开它,此时你看到的是所有的文字,但图片确实一张一张的下载后才能看到
代理模式UML图:
代理模式案例:
//抽象角色 声明真是对象和代理对象的共同接口 interface Subject{ public abstract void sendFower(); }//真实对象 class RealSubject implements Subject{ public void sendFower() { System.out.println("真实对象送花"); } }//代理对象 class ProxySubject implements Subject{ //代理对象内部包含真实对象的引用 private RealSubject realSubject; public void sendFower() { //在真实角色操作之前附加 preSend(); if(null==realSubject){ realSubject =new RealSubject(); } realSubject.sendFower(); //真实角色操作之后 postSend(); } public void preSend(){ System.out.println("送花之前考虑一下"); } public void postSend(){ System.out.println("送花后很高兴"); } }//客户端 public static void main(String[] args) { Subject subject = new ProxySubject(); subject.sendFower(); }以上就是静态代码。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。通过代理类实现了对对象的控制,客户端在调用真实对象前和后可以对信息进行一些预处理和后续处理。但也存在一些缺点,当代理类比较多的时候,就要改动代码生成代理对象。下面就介绍动态代理模式
//定义接口规则 interface Subject{ public void setName(String name); }//真实对象实现接口规则 class RealSubject implements Subject{ public void setName(String name) { System.out.println("姓名"+name+"开始送花"); } }//处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理类对象时都要指定一个对应的调用处理器对象。 class ProxyHandler implements InvocationHandler{ //要代理的真实对象 private Object proxied; public ProxyHandler(Object proxied){ this.proxied =proxied; } /** *Object proxy 第一个参数既是代理类实例, *Method method 第二个参数是被调用的方法对象 *Object[] args第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行 **/ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// //System.out.println("开始调用方法"+method.getName()+"参数"+Arrays.toString(args)); Object result =method.invoke(proxied, args) ; System.out.println("调用方法结束"); return result; } }public static void main(String[] args) { Subject realSubject = new RealSubject(); ProxyHandler proxyHandler =new ProxyHandler(realSubject); //newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) /** * ClassLoader loader 类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用 * Class<?>[] interfaces 一组接口 * InvocationHandler 调用处理器生成动态代理类实例 **/ Subject sub =(Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), proxyHandler); sub.setName("张三丰"); }
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/9407.html