代理模式
- 定义:为其他对象提供一种代理以控制对这个对象的访问
- 代理模式有如下角色:
- Subject:抽象主题类,声明真是主题与代理共同的接口方法
- RealSubject:真实主题类,代理类所代表的真实主题。客户端通过代理类间接地调用真实主题类的方法
- Proxy:代理类,持有对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行
- client:客户端类
- 代理模式有如下角色:
- 静态代理
- 抽象主题类
public abstract class Subject { public abstract void request(); }
- 真实主题类
public class RealSubject extends Subject{ @Override public void request() { System.out.println("realSub"); } }
- 代理类
public class Proxy extends Subject{ Subject mRealSubject; @Override public void request(){ if (mRealSubject != null){ System.out.println("Proxy request"); mRealSubject.request(); } } public Proxy(Subject mRealSubject) { this.mRealSubject = mRealSubject; } }
- 客户端类
public class Client { public static void main(String[] args){ Subject realSubject = new RealSubject(); Subject proxy = new Proxy(realSubject); proxy.request(); } }
- 抽象主题类
- 动态代理
- 要实现InvocationHandler接口
public class DynamicPurchaseing implements InvocationHandler { private Object object; public DynamicPurchaseing(Object object) { this.object = object; } @Override public Object invoke(Object o, Method method, Object[] objects) throws Throwable { Object result = method.invoke(object,objects); if (method.getName().equals("request")){ System.out.println("realSubject request----"); } return result; } }
- 在动态代理类中声明一个Object引用指向被代理的类,我们调用被代理类的具体方法(在这指RealSubject的request方法)是在invoke()方法中执行的
- 客户端代码:
public class Client { public static void main(String[] args){ Subject realSubject = new RealSubject(); DynamicPurchaseing dynamicPurchaseing = new DynamicPurchaseing(realSubject); ClassLoader classLoader = realSubject.getClass().getClassLoader(); //创建动态代理类 Subject pu = (Subject) java.lang.reflect.Proxy.newProxyInstance(classLoader,new Class[]{Subject.class} ,dynamicPurchaseing); pu.request(); } }
- 结果:
realSub realSubject request---- Process finished with exit code 0
-
首先我们解释一下为什么我们这里可以将其转化为Subject类型的对象?原因就是在newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现了这组接口,这个时候我们当然可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将其转化为Subject类型了。
同时我们一定要记住,通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号。
- 要实现InvocationHandler接口
- 优缺点:
- 真实主题类就是实现实际的业务逻辑,不用关心其他非本职的工作
- 真实主题类随时都会发生变化;但是因为它实现了公共的接口,所以代理类可以不做任何修改就能够使用
Dana.Lee
To:Dana_Lee1016@126.com