前言:
之前在学习JAVA基础的时候就知道有代理设计模式。不过,那个时候只是简单地学习了一下静态代理模式。今天在学习DAO设计模式时候,用到了工厂设计模式和代理设计模式。所以,就索性系统点的记录一下静态代理模式和动态代理模式。
概念:
何为代理模式?
答:代理模式,又称委托模式,顾名思义就是委托某物去处理某事。
例子:比如买火车票,我们可以到火车站窗口去购票,也可以去代理售票点购票。但是,逢年过节的时候,明显火车站都人从众。这时,我们就可以到代理售票点购票。代理购票点就相当于我们下面所要介绍的代理模式中代理角色。我们先委托代理售票点购票,代理售票点再向售票总部购票,从而达到购票目的。
代理模式主要作用是什么?
答:在开发中使用代理模式,可以降低耦合度。比如,两个类 Class A -----> Class B 。如此两个类的耦合度相比 Class A ---> Class C --->Class B 就要高。还有,例如在开发中操作数据库。我们的客户端只关系数据的操作,不关心数据库连接以及关闭,从而减少客户端代码。使用代理设计模式则可以达到这个目的。我们设计一个代理类进行操作数据库,并进行数据库的连接与关闭。我们在客户端操作数据库时,直接调用代理类就可以完成操作。另外,如果业务有需求,可以直接在代理中加入事务的处理功能,这样会使代码的开发结构更加清晰。
学习代理设计模式有什么好处?
答:JAVA中很多开源框架都使用到了代理设计模式,学习代理设计模式有助于后面学习以及理解这些新的知识。
代理模式简单包含几个部分?
答:抽象主题接口,真实主题类(实现抽象主题接口),代理类(静态代理或者动态代理)
示例:
静态代理设计模式:
抽象主题接口:
package com.kinglong.proxy; /* * 抽象主题 * */ public interface Subject { public void sayHello(); public void sayGoodbye(); }
真实主题类:
package com.kinglong.proxy; /* * 真实主题 * */ public class RealSubject implements Subject { @Override public void sayHello() { // TODO Auto-generated method stub System.out.println("Hello Work"); } @Override public void sayGoodbye() { // TODO Auto-generated method stub System.out.println("Goodbye Work"); } }
静态代理类:
package com.kinglong.proxy; /* * 静态代理 * */ public class StaticProxy implements Subject { RealSubject realSubject = null; public StaticProxy() { if (realSubject == null) { this.realSubject = new RealSubject(); } } @Override public void sayHello() { // TODO Auto-generated method stub this.postRealSubject(); this.realSubject.sayHello(); this.preRealSubject(); } @Override public void sayGoodbye() { // TODO Auto-generated method stub this.postRealSubject(); this.realSubject.sayGoodbye(); this.preRealSubject(); } public void postRealSubject() { System.out.println("before deal realSubject"); } public void preRealSubject() { System.out.println("after deal realSubject"); } }
客户端使用静态代理:
package com.kinglong.proxy; import java.lang.reflect.Proxy; /* * 测试静态代理模式与动态代理模式 * */ public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //静态代理 Subject subject = new StaticProxy(); subject.sayHello(); subject.sayGoodbye(); } }
从以上的静态代理可以看出来,如果现在一个项目有很多个主题的话,那么就需要为每一个主题编写一个静态代理类。这样一来,就会导致类的数量暴增,而且最重要的是静态代理类在实现的大体上是高度类似的。还有就是,如果主题类被修改了,那么静态代理类也一同被修改。所以,如果有一个代理类可以重复被各个主题类使用,那么就可以减少代码,提高代码利用率。所以就引出了我们下面要介绍的动态代理。
动态代理设计模式:
JAVA实现动态代理类,有JDK,CGLIB(第三方类库)。下面主要介绍的是使用JDK方式实现动态代理模式。JDK实现的动态代理有一个明显的限制就是,被代理的真实主题需要实现某个接口,继承则不行。如果需要让继承也能够使用,那则需要是使用第三方类库CGLIB实现。
抽象主题类:
同上
真是主题类:
同上
动态代理类:
package com.kinglong.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /* * 动态代理 * */ public class DynamicProxy implements InvocationHandler { Object object = null; public DynamicProxy(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub method.invoke(object, args); return this.object; } }
客户端使用动态代理:
package com.kinglong.proxy; import java.lang.reflect.Proxy; /* * 测试静态代理模式与动态代理模式 * */ public class Client { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub //动态代理 subject = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), RealSubject.class.getInterfaces(), new DynamicProxy(new RealSubject())); subject.sayHello(); subject.sayGoodbye(); } }