package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author jiq
* 类型:Structural
* 定义: 代理模式为另一个对象提供一个占位符(替身)以控制这个对象的访问。
* 话句话说,使用代理对象,可以让代理对象控制对某个对象的访问,被代理
* 的对象可以是远程对象,创建开销大的对象,或需要安全控制的对象。
*
* 为什么要控制访问:代理模式之所以要控制访问,是因为我们的客户不知道如何同
* 远程对象(被代理的对象)沟通。 比如远程代理访问,其帮助我们处理一些网络
* 上的细节。
*
* 区别: 装饰器模式包装一个对象,并提供额外的行为。
* 适配器模式包装一个对象,并转换成不同的接口(接口改变)。
* 外观模式包装许多对象,以简化他们的接口(接口改变)。
* 代理模式包装一个对象,并控制它的访问(不改变被代理对象的接口)。
* 其实虽然从结构上来看和Decorator模式类似,但Proxy是控制,更像是一种对功能的限制,
* 而Decorator是增加职责。
*
* 应用: Spring AOP的核心设计思想。 Java RMI(远程方法调用)
*
* 代码说明:由于一些特殊原因,客户端无法直接访问真正的主题(比如网络问题,并发换环境等)。
* 这个时候我们通过一个代理来控制对真正主题的访问,比如远程代理会帮忙处理一些网络上
* 的细节,多线程环境下的代理会帮忙解决一些同步问题等。 然后客户端通过代理来访问对象。
*/
interface Subject{
public void request();
}
/**
* 真正的角色,实现了request方法
* */
class RealSubject implements Subject{
public void request(){
System.out.print("real request handling\n");
}
}
/************************************************
* 静态代理,封装(控制)request方法的访问
************************************************/
class StaticProxySubject implements Subject{
private RealSubject realSubject; //组合被代理的对象
public void request(){
//do some thing else...
if(realSubject == null){
realSubject = new RealSubject();
}
realSubject.request(); //真正的request调用
//do some thing else...
}
}
/***********************************************************
* 动态代理. java.lang.reflect包中有自己的代理支持,利用这个包
* 你可以在运行时动态创建一个代理类,实现一个或者多个接口,并将
* 方法的调用转发到你所指定的类。
* 因为实际的代理类是在运行时创建的,所以我们称这个技术为动态代理。
* ***********************************************************/
class DynamicProxySubject implements InvocationHandler{
private Object realSubject; //组合被代理的对象
public DynamicProxySubject(Object realSubject){
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//do some thing else...
return method.invoke(realSubject, args);
//do some thing else...
}
}
/**************************************************
* 客户端,代理ProxySubject控制其对RealSubject的访问
* ************************************************/
public class ProxyTest {
public static void main(String[] args) {
//通过静态代理来访问对象
Subject proxy = new StaticProxySubject();
proxy.request();
//通过动态代理来访问对象
RealSubject real = new RealSubject();
Subject subject = (Subject) Proxy.newProxyInstance(
real.getClass().getClassLoader(), //定义代理类的类加载器
real.getClass().getInterfaces(), //代理类要实现的接口列表
new DynamicProxySubject(real)); //指派方法调用的调用处理程序
subject.request();
}
}
结构型-代理模式
最新推荐文章于 2024-03-11 23:59:46 发布