我如何最好地在Akka演员之间分享行为? [英] How do I best share behavior among Akka actors?

查看:63
本文介绍了我如何最好地在Akka演员之间分享行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个Akka演员以相同的方式响应某些消息,而其他人以不同的方式响应。它们都响应同一组消息。想知道如何通过继承,镇静等方式设计两个演员的接收方法吗?我尝试使用 orElse将其他特征的部分函数链接在一起,不幸的是,该类使类暴露于其特征的功能,而且我不确定该特征的接收如何可以轻松访问演员上下文。嵌入式的模块化解决方案将是理想的选择,但是我想知道这是否是一个可以解决的问题?

I have two Akka actors that respond to some messages in the same way, but others in a different way. They both respond to the same set of messages. Wondering how to design my two actors with their receive methods, via inheritance, composure, etc? I tried chaining together partial functions from other traits with "orElse", which unfortunately exposes the class to its trait's functionality, plus I wasn't sure how the trait's receive could easily access the actor context. A drop-in, modularized solution would be ideal, but I'm wondering if this is a solved problem somewhere?

推荐答案

确实,您可以采取多种方法。我将通过OO方式列出两种(类似于@Randal Schulz所建议的方式)和一种更实用的方式。对于第一个可能的解决方案,您可以执行以下简单操作:

There's really a bunch of ways that you can go about this. I'll list two from the OO way (similar to what @Randal Schulz is suggesting) and 1 more functional way. For the first possible solution, you could do something simple like this:

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) = {}
}

使用这种方法,您基本上定义了一个抽象actor impl,其中为所有处理的消息定义了 receive 函数。消息被委托给实际业务逻辑所在的 def s。两种是抽象的,让具体的类定义处理方式,一种在不需要逻辑不同的情况下完全实现。

With this approach, you define basically an abstract actor impl where the receive function is defined for all messages that are handled. The messages are delegated to defs where the real business logic would be. Two are abstract, letting the concrete classes define the handling and one is fully implemented for a case where the logic does not need to differ.

现在,此方法使用以下变体策略模式:

Now a variant on this approach using the Strategy Pattern:

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都将再次以相同的方式处理。两种方法非常相似,并且实现相同的目标。最后一种方法使用部分函数链,看起来可能像这样:

Here the approach is to pass in a strategy class during construction that defines the handling for a and c, with b again being handled the same regardless. The two approaches are pretty similar and accomplish the same goal. The last approach uses partial function chaining and could look like this:

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种消息类型的消息处理行为。具体参与者混合了这些特征,然后通过使用部分函数链来选择在构建接收函数时想要的行为。

Here, some traits are setup that define message handling behaviors for the 3 message types. The concrete actors mix in those traits and then pick which behaviors they want when building out their receive function by using partial function chaining.

可能还有许多其他方法可以实现您的需求,但我只是想为您提供一些选择。希望能帮助到你。

There are probably many other ways to do what you seek, but I just figured I'd throw a few options out there for you. Hope it helps.

这篇关于我如何最好地在Akka演员之间分享行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆