使用Futures和Promises进行延迟初始化是否合适,而不是使用Option var或一些可变变量?
您可以创建一个封装承诺的工厂类:
class IntFactory{
val intPromise = Promise[Int]
def create () : Future[Int] = intPromise.future
def init (data : String) : Unit = intPromise success data.length
}
演员或其他类可以像这样使用它:
class MyActor(factory : IntFactory) extends Actor{
val future_int = factory.create()
def receive = {
case (msg : String) => factory.init(msg) // Now the promise is fulfilled
}
}
做这样的事情有什么不对吗?以演员为例可能并不理想,因为我认为演员有更好的选择(成为或FSM)。我目前正在考虑将其与非演员类一起使用。某些实例变量在某些事件发生之前是无效的。我正在考虑这样做而不是使用var选项并将其设置为None。如果这很糟糕,还有什么其他选择?
修改
我想到了这可能更有用的情况。如果我有多个需要初始化的东西,并且在完成所有操作时我想要执行一些异步操作:
class MyActor(factory1 : IntFactory, factory2 : IntFactory) extends Actor{
val future_int1 = factory1.create()
val future_int2 = factory2.create()
for{
x <- future_int1
y <- future_int2
} // Do some stuff when both are complete
def receive = {
case "first" => factory1.init("first")
case "second" => factory2.init("second")
}
}
然后,每次我得到另一件时,我都不必检查哪些是无。
更多编辑:
我在原始问题中未指定的其他一些信息:
初始化对象所需的数据将异步进入。
初始化需要传递给init函数的数据。我编辑了我的示例代码,现在就是这种情况。
我没有使用Akka。我认为Akka将有助于拼凑一个简单的例子,并认为经验丰富的Akka人可以提供有用的反馈。
答案 0 :(得分:2)
是的,这肯定是比使用可变变量(无论是否为Option
)更好的方法。正如@PatrykĆwiek建议的那样,如果您可以随时初始化状态而不是等待外部事件而不需要异步执行,那么使用lazy val
会更好。
答案 1 :(得分:0)
从你的IntFactory
判断,你真的不需要data
字符串(它没有在任何地方使用),所以我认为可以像这样重写基本情况:
class Foo {
lazy val first = {
Thread.sleep(2000) // Some computation, initialization etc.
25
}
lazy val second = {
Thread.sleep(1000) // Some computation, initialization etc.
11
}
def receive(s : String) = s match {
case "first" => first
case "second" => second
case _ => -1
}
}
现在,让我们说你这样做:
val foo = new Foo()
println(foo.receive("first")) // waiting for 2 seconds, initializing
println(foo.receive("first")) // returns immediately
println(foo.receive("second")) // waiting for 1 second, initializing
现在first
和second
最多只能初始化一次。
您无法将参数传递给lazy val
,因此如果data
字符串对初始化有些重要,那么您最好使用具有memoization(IMO)的工厂方法。