标签:
代理模式的意图:
为其它对象提供代理,以控制对这个对象的访问。对一个对象进行访问控制的原因是为了我们在确实需要这个对象时才对它进行创建和初始化。有些对象创建的开销非常大,所以我们应该根据需要进行创建。Proxy则可以代替一个对象,并在需要时负责实例化这个对象。就像我们小学的时候总是欺负学习好的同学,让学习好的同学代替我们写作业,要不然我们放学就在路上堵着打他们,学习好的同学就乖乖的帮我们写作业,第二天到学校老师看了作业还表扬我们学习有进步呢。这就是一个很好的代理模式的例子。
代理模式的类图如下:
Subject:定义RealSubject和Proxy的公用接口,这样就在任何使用RealSubject的地方使用Proxy。
RealSubject :定义Proxy所对应的实体。
简单的说就是RealSuject和Proxy都实现了Subject接口,所以他们俩具有相同的方法,在realSubject中实现可该方法,而在Proxy中实现该方法时是调用Realsubject的方法。
代理模式的Java代码实现:
<pre name="code" class="java">package proxy; public interface AbstractClass { public void doHomeWork(); }
<pre name="code" class="java">package proxy; public class RealSubject implements AbstractClass { @Override public void doHomeWork() { System.out.println("我把家庭作业写完了..."); } }
package proxy; public class Proxy implements AbstractClass{ RealSubject sub = new RealSubject(); @Override public void doHomeWork() { System.out.println("替我写作业,要不然收拾你..."); sub.doHomeWork(); System.out.println("非常好..."); } }代理模式的适用性:
在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式。下面是一些可以使用Proxy模式的常见情况:
(1) 远程代理(Remote Proxy) :可以隐藏一个对象存在于不同地址空间的事实。
(2) 虚代理(Virtual Proxy):可以进行优化,根据需求进行创建对象。
(3)保护代理(Protection Proxy) :控制对原始对象的访问。
(4) 智能指引(Smart Reference):取代了简单指针,它在访问对象时执行一些附加操作。
动态代理:
上面所讲述的为静态代理,即一个实体类相对应的就具有一个代理类。静态代理之所以扩展和维护比较困难,是因为代码写的太死,没有可以替换的余地,针对于代码写死想到的办法就是使用反射机制来动态加载。动态代理即为:客户程序根据需要提供一组(1~N)个接口,然后运行时动态"声明"满足这些接口的类,客户程序可以用任何一个之前提供的接口调用这个类。
动态代理Java代码如下:
package proxy; public interface Book { public void add(); public void delete(); }
package proxy; public class BookImpl implements Book { @Override public void add() { System.out.println("添加图书信息..."); } @Override public void delete() { System.out.println("删除图书信息..."); } }
package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class LogerHander2 implements InvocationHandler { private Object targetObject; /** * 第一个参数:被代理类的类加载器 * 第二个参数: 被代理类以实现的所有接口 * 第三个参数: 用被代理类的实例创建动态代理类的实例,用于真正调用代理程序 * return: 返回实现了被代理类所实现的所有接口的Object对象,即动态代理 */ public Object newProxyInstance(Object targetObject){ this.targetObject = targetObject; return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("正在进行操作前的准备..."); Object result = method.invoke(targetObject, args); System.out.println("操作已经完成..."); return result; } }客户端测试类:
package proxy; public class Test { public static void main(String[] args) { // AbstractClass abs = new Proxy(); // abs.doHomeWork(); LogerHander2 loger = new LogerHander2(); Book book1 = (Book) loger.newProxyInstance(new BookImpl()); book1.delete(); book1.add(); } }动态代理通过运用反射的机制,通过运行期可以知道具体的加载那个类,避免了一个类对应一个代理的问题,同时通过统一的invoke方法,使动态代理很大程度上减少了重复的的代码,降低了维护的复杂性和成本。动态代理在一些框架中的用法非常之多,例如Spring的AOP、Hibernate中都有,有时间大家可以多去了解。
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/u013799929/article/details/47175101