3

Option var や変更可能な変数を使用するのではなく、遅延初期化に Future と Promises を使用するのは適切ですか?

promise をカプセル化するファクトリ クラスを作成できます。

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  
  }
}

このようなことをして何か問題がありますか?アクターを例として使用するのは理想的ではなかったかもしれません。アクターにはより良い代替手段 (become または 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") 
  }
}

そうすれば、別のピースを入手するたびにどれが None であるかを確認する必要がなくなります。

その他の編集:

元の質問で指定できなかった追加情報:

  1. オブジェクトの初期化に必要なデータは、非同期に取得されます。

  2. init 関数に渡されるデータは、初期化に必要です。これが当てはまるように、サンプルコードを編集しました。

  3. 私はアクアを使用していません。Akka は簡単な例をまとめるのに役立つと思い、Akka の経験豊富な人々が有用なフィードバックを提供できると考えました。

4

2 に答える 2

2

はい、これは確かに可変変数を使用するよりも優れたアプローチです (かどうかにOptionかかわらず)。lazy val@PatrykĆwiekが示唆したように、外部イベントを待つ代わりにいつでも状態を初期化でき、非同期で行う必要がない場合は、を使用する方がさらに優れています。

于 2013-11-04T08:57:59.137 に答える
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最大 1 回second初期化できるようになりました。

パラメータをlazy vals に渡すことはできないため、data文字列が初期化にとって何らかの形で重要な場合は、メモ化 (IMO) を使用したファクトリ メソッドを使用する方がよいでしょう。

于 2013-11-04T13:15:58.233 に答える