我正在尝试编写一个名为ActorManager
的actor,它包含另一个名为RealActor
的actor。我们的想法是ActorManager
可以处理进出RealActor
的所有消息,允许添加其他逻辑,如过滤或缓冲。外部世界应该只通过其经理与RealActor
进行沟通,就像在现实世界中一样。
初稿看起来像这样:
class ActorManager(realActor: ActorRef) extends Actor {
def receive = {
case _ => { /* pre-process messages */ }
}
}
class RealActor(actorManager: ActorRef) extends Actor {
def receive = {
case _ => { /* actual business logic */ }
}
}
然而,这提出了如何同时构建两个actor,或者更具体地说如何定义相应的Props
给定两个actor的循环依赖性的问题。在定义Props
时,我不确定general lazy val
pattern是否适用。
我还想避免先构建两个中的一个,然后引入一个明确的Register
协议来连接它们。
答案 0 :(得分:6)
通过使用actor层次结构而不是普通的actor兄弟来更好地解决这种情况。由于此处的主要目的是隐藏RealActor
来自外部世界,因此外部ActorRef
相应地包裹/拥有ActorManager
更为合理。
这意味着必须在RealActor
范围内创建ActorManager
引用。这可以通过传递父ActorRef => Props
函数来实现,允许创建子actor:
// Parent
class ActorManager(getRealActorProps: ActorRef => Props) extends Actor {
val realActor = context.actorOf(getRealActorProps(self))
def receive = {
case _ => { /* pre-process messages */ }
}
}
// Child
class RealActor(actorManager: ActorRef) extends Actor {
def receive = {
case _ => { /* actual business logic */ }
}
}
object RealActor {
def propsActorManager(getRealActorProps: ActorRef => Props) =
Props(new ActorManager(getRealActorProps))
def propsRealActor(actorManager: ActorRef) =
Props(new RealActor(actorManager))
def props() =
Props(new ActorManager(actorManager => propsRealActor(actorManager)))
}
请注意,现在甚至可以通过提供适当的RealActor
定义来隐藏props
被包装的事实,该定义隐式构建ActorManager -> RealActor
层次结构。
另见this blog post为什么平面演员层次结构被视为反模式。
答案 1 :(得分:1)
这种东西可能适合你:
import akka.actor._
class Manager extends Actor {
def realActor: ActorRef = context.child("real")
.getOrElse(context.actorOf(RealActor.props, "real"))
override def receive: Receive = {
case msg ⇒ realActor forward msg
}
}
object RealActor {
def props: Props = Props(new RealActor)
}
class RealActor extends Actor {
override def receive: Receive = {
case _ ⇒
}
}
通过父上下文创建子actor似乎足以创建父子层次结构。可以通过在子actor中调用context.parent来获取父级。