20

一部のメッセージに同じ方法で応答する 2 つの Akka アクターがいますが、別の方法で応答するものもあります。どちらも同じメッセージ セットに応答します。継承、コンポーズなどを介して、受信メソッドを使用して 2 つのアクターを設計する方法を知りたいですか? 「orElse」を使用して、他のトレイトの部分関数を連鎖させてみましたが、残念ながらクラスがそのトレイトの機能にさらされてしまいました。また、トレイトの receive がアクター コンテキストに簡単にアクセスする方法がわかりませんでした。ドロップインのモジュール化されたソリューションが理想的ですが、これはどこかで解決された問題でしょうか?

4

2 に答える 2

27

あなたがこれについて行くことができる方法は本当にたくさんあります。オブジェクト指向の方法 (@Randal Schulz が提案しているものと同様) から 2 つと、より機能的な方法を 1 つ挙げます。最初の可能な解決策として、次のような単純なことを行うことができます。

case class MessageA(s:String)
case class MessageB(i:Int)
case class MessageC(d:Double)

trait MyActor extends Actor{

  def receive = {
    case a:MessageA =>
      handleMessageA(a)

    case b:MessageB =>
      handleMessageB(b)

    case c:MessageC =>
      handleMessageC(c)
  }

  def handleMessageA(a:MessageA)

  def handleMessageB(b:MessageB) = {
    //do handling here
  }

  def handleMessageC(c:MessageC)
}

class MyActor1 extends MyActor{
  def handleMessageA(a:MessageA) = {}
  def handleMessageC(c:MessageC) = {}
}

class MyActor2 extends MyActor{
  def handleMessageA(a:MessageA) = {}
  def handleMessageC(c:MessageC) = {}
}

このアプローチでは、基本的に、receive処理されるすべてのメッセージに対して関数が定義されている抽象アクター impl を定義します。defメッセージは、実際のビジネス ロジックがある s に委任されます。2 つは抽象的で、具体的なクラスで処理を定義できます。もう 1 つは、ロジックが異なる必要がない場合に備えて完全に実装されています。

Strategy パターンを使用したこのアプローチの変形:

trait MessageHandlingStrategy{
  def handleMessageA(a:MessageA)

  def handleMessageB(b:MessageB) = {
    //do handling here
  }

  def handleMessageC(c:MessageC)
}

class Strategy1 extends MessageHandlingStrategy{
  def handleMessageA(a:MessageA) = {}
  def handleMessageC(c:MessageC) = {}  
}

class Strategy2 extends MessageHandlingStrategy{
  def handleMessageA(a:MessageA) = {}
  def handleMessageC(c:MessageC) = {}  
}

class MyActor(strategy:MessageHandlingStrategy) extends Actor{

  def receive = {
    case a:MessageA => 
      strategy.handleMessageA(a)

    case b:MessageB =>
      strategy.handleMessageB(b)

    case c:MessageC =>
      strategy.handleMessageC(c)
  }
}

ここでのアプローチは、構築中に a と c の処理を​​定義する戦略クラスを渡すことです。b は関係なく同じように処理されます。2 つのアプローチは非常に似ており、同じ目標を達成します。最後のアプローチは、部分的な関数チェーンを使用しており、次のようになります。

trait MessageAHandling{
  self: Actor =>
  def handleA1:Receive = {
    case a:MessageA => //handle way 1
  }
  def handleA2:Receive = {
    case a:MessageA => //handle way 2
  }  
}

trait MessageBHandling{
  self: Actor =>
  def handleB:Receive = {
    case b:MessageB => //handle b
  }  
}

trait MessageCHandling{
  self: Actor =>
  def handleC1:Receive = {
    case c:MessageC => //handle way 1
  }
  def handleC2:Receive = {
    case c:MessageC => //handle way 2
  }  
}

class MyActor1 extends Actor with MessageAHandling with MessageBHandling with MessageCHandling{
  def receive = handleA1 orElse handleB orElse handleC1
}

class MyActor2 extends Actor with MessageAHandling with MessageBHandling with MessageCHandling{
  def receive = handleA2 orElse handleB orElse handleC2
}

ここでは、3 つのメッセージ タイプのメッセージ処理動作を定義するいくつかの特性が設定されています。具体的なアクターは、これらの特性を混ぜ合わせてから、receive部分的な関数チェーンを使用して関数を構築するときに必要な動作を選択します。

あなたが求めていることを行うにはおそらく他にも多くの方法がありますが、私はあなたのためにいくつかのオプションを投げると思いました. それが役に立てば幸い。

于 2013-06-29T23:41:19.827 に答える