对于......
的方法...需要缓存结果值。
在我的代码中,以下结果值缓存模式重复了很多(Java中的伪代码,但问题与语言无关):
private static Map<Input, Output> fooResultMap = new HashMap<Input, Output>();
public getFoo(Input input) {
if (fooResultMap.get(input) != null) {
return fooResultMap.get(input);
}
Output output = null;
// Some code to obtain the object since we don't have it in the cache.
fooResultMap.put(input, output);
return output;
}
一直重复这种结构明显违反DRY原则。
理想情况下,我希望将上面的代码简化为以下内容:
@CacheResult
public getFoo(Input input) {
Output output = null;
// Some code to obtain the object since we don't have it in the cache.
return output;
}
理论上的CacheResult注释会处理我目前正在手工完成的缓存。
此类缓存的一般术语是“memoization”。
我正在寻找的确切功能的一个很好的例子是Perl core module "Memoize"。
在哪种语言中存在类似Memoize的缓存解决方案(在语言级别或库级别)?特别是 - 对于任何主要平台,例如Java或.NET,是否存在这样的解决方案?
答案 0 :(得分:4)
不是内置的语言,我认为CPAN模块Memoize在Perl土地上相当受欢迎:
# Compute Fibonacci numbers
sub fib {
my $n = shift;
return $n if $n < 2;
fib($n-1) + fib($n-2);
}
use Memoize;
memoize('fib');
答案 1 :(得分:2)
缓存处理程序 - 在.Net'企业库'中
http://msdn.microsoft.com/en-us/library/cc511757.aspx
[CachingCallHandler(0, 0, 30)]
public decimal GetSavingsBalance(int accountNumber)
{
// Code here to extract balance from database.
return balance;
}
答案 2 :(得分:1)
Python有许多装饰器配方,例如decorator module,适用于此( if 参数都是不可变的),并且它在JVM和.NET上都有实现。
答案 3 :(得分:1)
Spring的孵化区域 springmodules 具有Java的这一功能。
Springmodules cache 仍然处于0.8版本的水平,但是当我去年试用它时,它的效果一般都很好。有一些选项可以在spring配置文件和注释中配置缓存 - 这看起来与您的示例非常相似。来自他们的文档:
public class TigerCacheableService implements CacheableService {
@Cacheable(modelId = "testCaching")
public final String getName(int index) {
// some implementation.
}
...
}
您可以选择缓存的后端实现。当我尝试它时,我有很好的结果将它连接到ehcache,它也有很好的弹簧集成。您可以声明性地设置ehcache来缓存(内存和/或磁盘)您使用 @Cacheable
注释标记的方法的结果。
答案 4 :(得分:0)
答案 5 :(得分:0)
Microsoft T-SQL可以缓存来自pr的CLR函数的返回值。查询依据......
(在CLR中写入时,除了方法的正确属性外没有样板。)
答案 6 :(得分:-1)
不是您问题的直接答案,但如果您要维护许多缓存,则使用OSCache(Java)来管理这些缓存可能是值得的。驱逐陈旧物品等,成为您不必担心的问题。
你仍然需要使用“检查缓存”,“返回缓存”或“创建并添加到缓存”的基本模式。
答案 7 :(得分:-1)
虽然Java的语法仍然很详细,但可以将Java中的代码分解出来,
private static final Cache<Input, Output> fooCache = Caches.newInstance(
new Factory<Input, Output>() { public Output create(Input input) {
return ... some code ...;
}}
);
public static Output getFoo(Input input) {
return fooCache.get(input);
}
通过对匿名内部类的更好的语法支持,可能会变成,例如:
private static final Cache<Input, Output> fooCache =
(Input input) (... some code ...);
public static Output getFoo(Input input) {
return fooCache.get(input);
}
这是AOP解决方案可以做的一件事,代价是不得不处理一些魔法。
答案 8 :(得分:-1)
This question/answer解决了C#中的Memoization问题。它不会缓存结果,但可以通过ReaderWriterLock轻松更改以使地图静态。
以下是link given的示例:
public static Func<A, R> Memoize<A, R>(this Func<A, R> f)
{
var map = new Dictionary<A, R>();
return a =>
{
R value;
if (map.TryGetValue(a, out value))
return value;
value = f(a);
map.Add(a, value);
return value;
};
}