我真的很喜欢@senia 的解决方案。这是对 Akka 新的 Typed Channels 功能的有效使用。但是,如果该解决方案不适合您,我可以为 OO 世界提供一些更传统的东西。在此解决方案中,您可以通过构造 Actor 的策略实现来指定 Actor 的实际消息处理行为。代码看起来像这样:
//Strategy definition
trait FooStrategy{
def foo1(s:String):String
def foo2(i:Int):Int
}
//Regular impl
class RegularFoo extends FooStrategy{
def foo1(s:String) = ...
def foo2(i:Int) = ...
}
//Other impl
class AdvancedFoo extends FooStrategy{
def foo1(s:String) = ...
def foo2(i:Int) = ...
}
//Message classes for the actor
case class Foo1(s:String)
case class Foo2(i:Int)
//Actor class taking the strategy in the constructor
class FooActor(strategy:FooStrategy) extends Actor{
def receive = {
case Foo1(s) => sender ! strategy.foo1(s)
case Foo2(i) => sender ! strategy.foo2(i)
}
}
然后创建这个actor的实例:
val regFooRef = system.actorOf(Props(classOf[FooActor], new RegularFoo))
val advFooRef = system.actorOf(Props(classOf[FooActor], new AdvancedFoo))
这里的一个好处是您将参与者的业务逻辑与其正常的消息处理行为分离。您让演员类只做演员的事情(从邮箱接收,回复发件人等),然后将真正的业务逻辑封装在一个特征中。这也使得使用 trait impls 的单元测试单独测试业务逻辑变得更加容易。如果您在 trait impls 中需要演员类型的东西,那么您总是可以ActorContext
为 on 方法指定一个隐式的FooStrategy
,但是您将失去演员和业务逻辑的完全解耦。
就像我之前说的,我喜欢@senia 的解决方案;我只是想给你另一个可能更传统的面向对象的选择。