我有两个Akka演员以同样的方式回复某些消息,但其他人以不同的方式。它们都响应同一组消息。想知道如何使用他们的接收方法设计我的两个演员,通过继承,镇定等?我尝试将其他特征的部分函数与“orElse”链接在一起,遗憾的是,它将类暴露给它的特征的功能,而且我不确定特征的接收如何能够轻松访问actor的上下文。一个简单的,模块化的解决方案将是理想的,但我想知道这是否是一个解决的问题?
答案 0 :(得分:25)
有很多方法可以解决这个问题。我将从OO方式列出两个(类似于@Randal Schulz所建议的)和另外一个功能方式。对于第一个可能的解决方案,你可以做一些简单的事情:
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
。两个是抽象的,让具体类定义处理,一个完全实现,逻辑不需要区别。
现在使用策略模式的这种方法的变体:
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再次被处理相同。这两种方法非常相似,可以实现相同的目标。最后一种方法使用部分函数链,看起来像这样:
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
函数时选择他们想要的行为。
可能还有很多其他方法可以做你想要的,但我只是觉得我会为你提供一些选择。希望能帮助到你。
答案 1 :(得分:5)
到目前为止,我没有理由后悔将我的服务的实际功能(所谓的“业务逻辑”)推送到较低层,“常规”和同步(有时是阻塞)库,经过单元测试,没有演员的复杂情况。我在Actor类中唯一放置的是传统库代码所处的共享的长期可变状态。当然,这是Akka Actor receive
函数的消息解码和调度逻辑。
如果你这样做,以你寻求的方式分享逻辑是微不足道的。