如何与它的包装器一起构造一个actor?

时间:2017-03-24 14:45:53

标签: scala akka

我正在尝试编写一个名为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协议来连接它们。

2 个答案:

答案 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来获取父级。