知识大全 浅谈Java中用动态代理类实现记忆功能

Posted 记忆

篇首语:幼苗需要土壤的滋养,孩子需要教师的爱护。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 浅谈Java中用动态代理类实现记忆功能相关的知识,希望对你有一定的参考价值。

浅谈Java中用动态代理类实现记忆功能  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  记忆是衍生自Lisp Python和Perl等过程性语言的一种设计模式 它可以对前次的计算结果进行记忆 一个实现了记忆功能的函数 带有显式的cache 所以 已经计算过的结果就能直接从cache中获得 而不用每次都进行计算

  记忆能显著的提升大计算量代码的效率 而且是一种可重用的方案

  本文阐述了在Java中使用这一模式的方法 并提供了一个可以提供上述功能的 记忆类

  Foo foo = (Foo) moize(new FooImpl()) 这里 Foo是一个接口 它含有的方法是需要记忆的 FooImpl是Foo的一个实现 foo是Foo的一个引用 方法与FooImpl基本相同 区别在于Foo返回的值 会被缓存起来 单个记忆类的优点在于为任何类添加记忆功能是很简单的 定义一个包含需要记忆的方法的接口 然后调用memoize来实现一个实例

  为了理解记忆类是怎么实现的 我们将分几步来解释 首先 我解释一下为何缓存能够在需要它的类中实现 然后 我测试一下如何为一个特定的类添加缓存包装器 最后 我解释一下如何才能使得一个缓存包装器能够通用于任意的类

  为大计算量的程序添加缓存

  作为一个大计算量程序的例子 我们考虑PiBinaryDigitsCalculator这个例子 计算二进制数据pi 仅有的public方法calculateBinaryDigit带有一个参数 整数n 代表需要精确到的位数 例如 将会返回小数点后的一百万位 通过byte值返回 每位为 或者

  public class PiBinaryDigitsCalculator /** * Returns the coefficient of ^n in the binary * expansion of pi * @param n the binary digit of pi to calculate * @throws ValidityCheckFailedException if the validity * check fails this means the implementation is buggy * or n is too large for sufficient precision to be * retained */ public byte calculateBinaryDigit(final int n) return runBBPAlgorithm(n)

  private byte runBBPAlgorithm(final int n) // Lengthy routine goes here ……

  

  

  最简单直接的方法来缓存返回值可以通过修改这个类来实现 添加一个Map来保存之前计算得到的值 如下

  import java util HashMap public class PiBinaryDigitsCalculator

  private HashMap cache = new HashMap()

  public synchronized byte calculateBinaryDigit(final int n)

  final Integer N = new Integer(n) Byte B = (Byte) cache get(N) if (B == null) byte b = runBBPAlgorithm(n) cache put(N new Byte(b)) return b else return B bytevalue()

  private byte runBBPAlgorithm(final int n) // Lengthy routine goes here ……

  

  calculateBinaryDigit方法首先会检查HashMap里面是否缓存了这个关键字 参数n 如果找到了 就直接返回这个值 否则 就会进行这个冗长的计算 并将结果保存到缓存里面 在添加进HashMap的时候 在原始类型和对象之间还要进行小小的转换

  尽管这个方法是可行的 但是 有几个缺点 首先 进行缓存的代码和正常的算法代码不是显著分开的 一个类 不仅负责进行计算 也要负责进行维护缓存数据 这样 要进行一些测试就会显得很困难 比如 不能写一个测试程序来测试这个算法持续地返回相同的值 因为 从第二次开始 结果都是直接从cache中获得了

  其次 当缓存代码不再需要 移除它会变得困难 因为它和算法块的代码是紧密结合在一起的 所以 要想知道缓存是否带来了很高的效率提升也是很困难的 因为不能写一个测试程序是和缓存数据分开的 当你改进了你的算法 缓存有可能失效 但是这个时候你并不知道

  第三 缓存代码不能被重用 尽管代码遵从了一个普通的模式 但是都是在一个类 PiBinaryDigitsCalculator里面

  前面两个问题都可以通过构造一个缓存包装器来解决

  缓存包装器

  通过使用Decorator模式 要分开计算代码和缓存代码是很容易的 首先 定义一个接口 里面定义基本的方法

  public interface BinaryDigitsCalculator public byte calculateBinaryDigit(final int n) 然后定义两个实现 分别负责两个任务

  public class PiBinaryDigitsCalculator implements BinaryDigitsCalculator

  public byte calculateBinaryDigit(final int n) return runBBPAlgorithm(n)

  private byte runBBPAlgorithm(final int n) // Lengthy routine goes here ……

  

  import java util HashMap

  public class CachingBinaryDigitsCalculator implements BinaryDigitsCalculator

  private BinaryDigitsCalculator binaryDigitsCalculator private HashMap cache = new HashMap()

  public CachingBinaryDigitsCalculator(BinaryDigitsCalculator calculator) this binaryDigitsCalculator = calculator

  public synchronized byte calculateBinaryDigit(int n) final Integer N = new Integer(n) Byte B = (Byte) cache get(N) if (B == null) byte b = binaryDigitsCalculator calculateBinaryDigit(n) cache put(N new Byte(b)) return b else return B bytevalue()

  这是很之前的实现PiBinaryDigitsCalculator的一种简单的refactored版本

cha138/Article/program/Java/hx/201311/25515

相关参考

知识大全 JAVA 动态代理

JAVA动态代理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  在目前的Java开发包中包含了对

知识大全 Java 实践: 用动态代理进行修饰

Java实践:用动态代理进行修饰  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  动态代理工具是j

知识大全 java动态代理Dynamic Proxy

java动态代理DynamicProxy  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  被代理对

知识大全 Java动态代理机制综合分析及扩展

Java动态代理机制综合分析及扩展  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Java动态代

知识大全 Java设计模式-----Proxy模式(动态代理)

Java设计模式-----Proxy模式(动态代理)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

知识大全 spring技术手册上的一个java动态代理例子

  Java代码  publicinterfaceIHello  publicvoidhello(Stringname);    Java代码  publicclassHelloImplimpleme

知识大全 动态代理

  动态代理  要求测算一个类里面的某个方法的执行时间  直接在一个测试的方法中调用这个类的方法就可以了也可以直接的写在这个类的main方法里面  继承这个类对需要测算时间的方法进行重写方法中这样来写

知识大全 实现动态代理的介绍和使用

  引言  假如现在我们有这样在这个示例中我将使用尽可能简单的逻辑实现所有功能需求这将更突出我们所要解决的核心问题例子是一个简单计算器类  publicclassCalculator pub

知识大全 JVM技术,反射与动态代理

JVM技术,反射与动态代理  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Java程序的工作机制

知识大全 java反射机制

  JAVA反射机制是在运行状态中对于任意一个类都能够得到这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制