现在的位置: 首页 > 综合 > 正文

结构型-代理模式

2019年10月16日 ⁄ 综合 ⁄ 共 2260字 ⁄ 字号 评论关闭
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();
	}
}


抱歉!评论已关闭.