您将如何在 Scala 中实现缓存方面
Posted
技术标签:
【中文标题】您将如何在 Scala 中实现缓存方面【英文标题】:How would you implement a caching aspect in Scala 【发布时间】:2014-05-07 10:16:20 【问题描述】:头脑风暴:我正在开发一个 Scala 项目,我们在该项目中进行服务调用,并且需要使用 memcache 缓存返回值。我正在开发一个 Python 项目,used decorators 来注释应该缓存其返回值的函数。我正在 Scala 中寻找一种类似的方式来向函数添加缓存方面。
假设我有这个功能def callingService(arg1: String, arg2: Int): String
我想要
任何调用 callingService 的代码都不应该知道缓存。 callService 的实现应该只是调用服务 X 并返回一个 String 值,而不是处理缓存的东西。
【问题讨论】:
【参考方案1】:我更喜欢 Stackable Trait Pattern 和 Cake Pattern:
class Service
def callingService(arg1: String, arg2: Int): String = "ok"
trait Memo[K, V]
def cache(k: K)(v : => V): V
trait ServiceCache extends Service
self : Memo[(String, Int), String] =>
abstract override def callingService(arg1: String, arg2: Int): String =
cache((arg1, arg2)) super.callingService(arg1, arg2)
trait MapCache[K, V] extends Memo[K, V]
private val _cache = new collection.mutable.HashMap[K, V]
def cache(k: K)(v : => V): V = _cache.getOrElseUpdate(k, v)
使用示例:
val service = new Service with ServiceCache with MapCache[(String, Int), String]
当然,您可以实施自己的缓存策略并在创建服务时与之混合
【讨论】:
请注意,蛋糕模式可能会引入过多的样板,最终可能会成为难以维护的模式之一。我最近遇到了类似的情况,最终不得不摆脱蛋糕图案。可能是 Reader monad 可以是更好的选择或隐含的。奥德斯基在尝试其他替代方案后宣布隐含是他的选择。检查这个:groups.google.com/forum/#!msg/scala-user/n50RW4gQBS4/…【参考方案2】:我不知道在 Scala 中自动执行此操作的方法。我想你会自己做。
您希望任何调用代码都知道缓存。我认为做到这一点的唯一方法是在函数本身内部拥有缓存机制。
为什么不使用闭包:
val cachedFunc =
val cache = mutable.Map[Int, Double]()
def internalFunc(y: Int) : Double = Math.sqrt(y);
(y: Int) =>
if (cache.keySet.contains(y))
cache(y)
else
val result = internalFunc(y);
cache += y -> result;
result
现在你可以:
cachedFunc(200)
【讨论】:
【参考方案3】:scalaz 提供了一个不错的缓存实现:http://eed3si9n.com/learning-scalaz-day16
【讨论】:
以上是关于您将如何在 Scala 中实现缓存方面的主要内容,如果未能解决你的问题,请参考以下文章