善用设计模式-代理模式

一、为什么要用代理模式

        1).安全考虑:可以屏蔽客户端直接访问真实对象;

        2).延迟对真实对象的加载,提升系统启动时间;

        3).在代理类中可进行类似AOP编程

二、实用场景(转)

       1) 远程代理(Remote  Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。如果让你直接coding去调用,你需要处理网络连接、处理打包、解包等等非常复杂的步骤,所以为了简化客户端的处理,我们使用代理模式,在客户端建立一个远程对象的代理,客户端就象调用本地对象一样调用该代理,再由代理去跟实际对象联系,对于客户端来说可能根本没有感觉到调用的东西在网络另外一端,这实际上就是Web Service的工作原理。
       2) 虚拟代理(Virtual Proxy)如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。 
       3) 保护代理(Protection Proxy)控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
       4) 智能指引(Smart Reference)取代了简单的指针,它在访问对象时执行一些附加操作。
       5) Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。

三、代理模式涉及角色

      1) 代理主题接口

      2) 真实主题类

      3) 代理类

      4) 调用端

四、具体实现方法

      1) 静态代理

       

/**
 * @author pengl
 * 2014-5-3
 * 描述:代理模式的主题接口
 */
public interface IDBQuery {
	public String query();
}

/**
 * @author pengl
 * 2014-5-3
 * 描述:真实主题类
 */
public class DBQuery implements IDBQuery {
	public String query() {
		return "query strings";
	}
	
}

/**
 * @author pengl
 * 2014-5-3
 * 描述:代理类
 */
public class DBQueryProxy implements IDBQuery{
	private DBQuery dbQuery = null;
	public String query() {
		if(dbQuery==null){
			dbQuery = new DBQuery();
		}
		return dbQuery.query();
	}
}

/**
 * @author pengl
 * 2014-5-3
 * 描述:客户端调用
 */
public class Main {
	public static void main(String[] args) {
		IDBQuery query = new DBQueryProxy();
		query.query();
	}
}

      2) 动态代理

/**
 * @author pengl
 * 2014-5-3
 * 描述:代理模式的主题接口
 */
public interface IDBQuery {
	public String query();
}

/**
 * @author pengl
 * 2014-5-3
 * 描述:真实主题类
 */
public class DBQuery implements IDBQuery {	
	public String query() {
		return "query strings";
	}
	
}

/**
 * @author pengl
 * 2014-5-3
 * 描述:代理类[java动态代理]
 */
public class DynamicProxyFactory implements InvocationHandler{
	private Object object;
	public DynamicProxyFactory(Object obj){
		this.object = obj;
	}
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		/**
		 * 我们可以在这个封装的动态代理类里添加日志等操作
		 */
		Logger.getLogger(this.getClass()).warn("开始调用动态代理类");
		method.invoke(object, args);
		Logger.getLogger(this.getClass()).warn("调用动态代理类结束");
		return null;
	}
}

/**
 * @author pengl
 * 2014-5-3
 * 描述:客户端调用
 */
public class Main {
	public static void main(String[] args) {
		IDBQuery query = new DBQuery(); //被代理类
		InvocationHandler ih = new DynamicProxyFactory(query); //初始化代理类
		IDBQuery proQuery = (IDBQuery) Proxy.newProxyInstance(query.getClass().getClassLoader(), query.getClass().getInterfaces(), ih);
		proQuery.query();
	}
}


          上面演示的只是JDK自带的动态代理,还有CGLIB、Javassist、ASM等实现库。如Hibernate框架中的load查询,就是使用的CGLIB实现库。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值