您的位置:软件 > 开发者网络 > 开发工具 > Java > 正文
用Java动态代理类实现记忆功能
[文章信息]
作者:Matrix-chris
时间:2003-09-13
出处:Matrix
责任编辑:方舟
[文章导读]
本文阐述了在Java中使用这一模式的方法,并提供了一个可以提供上述功能的"记忆类"
advertisement
热点推荐
· 天极网软件频道改版调查
· 在ASP.NET程序中创建唯一序号
· 用JVM工具接口创建调试和分析代理
· Win 2000如何安装配置防火墙
· 防范Windows消息钩子的侵入
[正文]

上一页  1 2 3 4  下一页

  通过动态代理类来创建一个通用的缓存包装器

  上面第二种方法仅有的缺点就是缓存包装器不能重用,每次我们希望添加一个缓存给某个类,我们就要写一个特殊的缓存包装器给目标接口.这是一个很慢,容易出错的过程.

  Jdk1.3开始支持动态代理类: 特别的类能够在运行期决定实现哪个接口-通常的模式都是,在运行期即决定实现哪个接口.通过这个,我们有可能实现一个通用的缓存包装器,我们称它为Memoizer,在运行期决定实现哪个接口.这样, CachingBinaryDigitsCalculator就是不再需要的.它是这样被调用的:

BinaryDigitsCalculator calculator =
new CachingBinaryDigitsCalculator(
new PiBinaryDigitsCalculator()
);

  可以通过Memoizer来重写如下:

BinaryDigitsCalculator calculator =
(BinaryDigitsCalculator) Memoizer.memoize(
new PiBinaryDigitsCalculator()
);

Memoizer的代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Memoizer implements InvocationHandler {
public static Object memoize(Object object) {
return Proxy.newProxyInstance(
object.getClass().getClassLoader(),
object.getClass().getInterfaces(),
new Memoizer(object)
);
}

private Object object;
private Map caches = new HashMap();

private Memoizer(Object object) {
this.object = object;
}

public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {

if (method.getReturnType().equals(Void.TYPE)) {
// Don't cache void methods
return invoke(method, args);
} else {
Map cache = getCache(method);
List key = Arrays.asList(args);
Object value = cache.get(key);

if (value == null && !cache.containsKey(key)) {
value = invoke(method, args);
cache.put(key, value);
}
return value;
}
}

private Object invoke(Method method, Object[] args)
throws Throwable {
try {
return method.invoke(object, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}

private synchronized Map getCache(Method m) {
Map cache = (Map) caches.get(m);
if (cache == null) {
cache = Collections.synchronizedMap(
new HashMap()
);
caches.put(m, cache);
}
return cache;
}
}

  当调用静态方法memoize的时候,将会创建一个新的代理实例-也就是一个java.lang.reflect.proxy的实例.实现了一个接口集.这个接口集由object.getClass().getInterfaces()来决定.每个代理实例包含一个java.lang.reflect.InvocationHandler实例来处理这个代理实例调用的相关方法.在我们的例子里,Memoizer就是一个InvocationHandler实例.

  当一个方法在代理实例里被调用,比如, calculateBinaryDigit,那么, Memoizer实例里的invoke方法就会被调用,相关信息会传给invoke方法,以决定proxy实例调用了哪个方法,包含参数信息.在我们的例子里,传入Memoizer的java.lang.Method参数是calculateBinaryDigit,而参数信息则是pi需要精确的位数-整数n.在这个基础上,Memoizer能够进一步进行缓存操作的.

  在例子里(caches是一个Hashmap,cache是一个map)里用到的Key,主要是传入的方法信息:Method对象和参数对象. 为了实现的简单与通用性,Memoizer有一个关于cache的HashMap caches,每个method是一个key,对应的value为一个cache.然后把参数信息转化成一个List对象,作为cache的Key.使用List是很方便的,同时也可以保证equals()方法,所以能够保证当且仅当参数信息完全相同的时候这个List才相等.

  一旦一个cache的Key被创建,那么,计算之前都会先查找这个cache,如果找到,则返回cache里的值.否则,如果带有这些参数的这个方法没有被调用过,那么,则会通过invoke来调用这个method.在我们的例子里, 实例PiBinaryDigitsCalculator 里的calculateBinaryDigit方法将会通过invoke被调用.而且计算结果将会被存在cache里.


上一页  1 2 3 4  下一页

·"WAP天极之IT新闻资讯,50万元等你拿"    ·天极WAP之游戏狂图,50万元等你下载


发表评论推荐给朋友我想参加相关培训打印我对此感兴趣订阅电子杂志
相关内容阅读排行榜
  • Servlet容器工作原理
  • WebSphere SAP适配器编程基础
  • 在Java中使用正则表达式
  • Forte For Java开发指南
  • JBuilder9的WEB服务介绍
  • 主板超频特色技术GIGA技嘉篇
  • Win 2000如何安装配置防火墙
  • 防范Windows消息钩子的侵入
  • 性价比之选 AGP显卡的告别秀
  • 大学校园生活之聊天也疯狂
  • Fireworks制作GIF动画Banner
  • 金山打击外挂 遭网络游戏玩家起诉
  • 完全公测《开天》掀起滔滔巨浪
  • Advertisement