Akka类型动作者功能与面向对象方法的比较研究

zbdgwd5y  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(94)

我曾经研究过Akka角色(非类型化),最近开始编写Akka类型化角色,发现有两种实现方式,一种是函数式的,另一种是面向对象的(类似于旧的)。
我对理解函数式和面向对象方式的状态封装很感兴趣,所以为函数式写了一个方法,为面向对象方式写了一个类。

功能方式:

def webSocketConnections(l: List[ActorRef[Message]] = List.empty): Behavior[WebSocketMsg] = {
    Behaviors.receive[WebSocketMsg] {
      (context, message) => {
        message match {
          case Model.UserAdded(actorRef) => webSocketConnections(actorRef :: l)
          case Model.BroadcastToAll(msg) =>
            context.spawnAnonymous(broadCastActorBehaviour) ! Broadcast(l, msg)
            Behaviors.same
        }
      }
    }
  }

面向对象的方法

class WebSocketConnectionMaintainer(actorContext: ActorContext[WebSocketMsg]) extends
  AbstractBehavior[WebSocketMsg](actorContext) {
  private var actorRefL: List[ActorRef[Message]] = List.empty

  override def onMessage(msg: WebSocketMsg): Behavior[WebSocketMsg] = {
    msg match {
      case Model.UserAdded(actorRef) =>
        actorRefL =  actorRef :: actorRefL
        Behaviors.same
      case Model.BroadcastToAll(msg) =>
        actorContext.spawnAnonymous(broadCastActorBehaviour) ! Broadcast(actorRefL, msg)
        Behaviors.same
    }
  }
}

如果您观察到这两种情况,在函数方式的情况下,状态被封装为参数,不确定它是否会有堆栈安全方面的问题,因为它可能会在大量调用后由于堆栈溢出错误而崩溃,对吗?
但是如果你观察面向对象的方式,它只是直接改变列表,不会导致任何堆栈溢出问题。
我发现的另一个问题是,我只能使用context.spawn来生成函数式的方式参与者,但在面向对象的情况下,我需要一个特定类型的上下文。如果我想同时创建函数式和面向对象的参与者,该怎么办?

pb3skfrl

pb3skfrl1#

关于栈的安全问题,简单的回答是,表观递归是蹦床式的,所以它不会破坏栈。参见this StackOverflow question
要生成一个OO定义的类型化参与者,可以使用Behaviors.setup,它注入上下文:

def ooBehavior: Behavior[WebSocketMsg] = Behaviors.setup { ctx =>
  new WebSocketConnectionMaintainer(ctx)
}
context.spawn(ooBehavior)

相关问题