访问akka / scala中actor之外的不可变成员

我刚开始学习Akka /
Scala,我写了一个小聊天服务器.

想象一下,这是一个基于房间的聊天服务器,每个人都可以创建自己的房间,可以同时在几个房间.每当房间里的房间用完时,房间就会关闭.房间由id:Int标识,并具有不可变的名称:String.我写了下面的代码来介绍房间.

class Room(val id: Int, val name: String, var host: ActorRef) extends Actor {
  def receive = {
    case GetId() =>
      sender ! id
    case GetName() =>
      sender ! name
    case AddMember(member) => ...
    case RemoveMember(member) => ...
    case BroadcastMessage(from, message) => ...
}

现在,客户需要所有房间的ID和名称,以决定加入哪个房间.

val rooms: List[ActorRef] // Obtained somewhere
val getIdFutures: List[Future[Int]] = rooms.map { (_ ? GetId()).mapTo[Int] }
val getNameFutures: List[Future[String]] = rooms.map { (_ ? GetName()).mapTo[String] }
val getIds: Future[List[Int]] = Future.sequence(getIdFutures)
val getNames: Future[List[String]] = Future.sequence(getNameFutures)
for (ids <- getIds; names <- getNames) yield {
  ids zip names map { pair =>
    val id = pair._1
    val name = pair._2
    println(s"$id: $name")
  }
}

嗯,好吧,它的工作原理……但是……有没有办法让我更方便地访问Actor中的那些不可变成员?我试图为房间演员制作一个包装器,如下面的代码:

case class RoomWrapper(val id: Int, val name: String, actor: ActorRef)

看起来很好,但有一个问题:现在我必须到处传递RoomWrapper对象.如何在房间被毁时收到通知?我无法上下文.观看一个RoomWrapper!

怎么解决这个?我有可能这样写吗?

val rooms: List[ActorRef]
rooms map { room =>
  println(room.id)
  println(room.name)
}

最佳答案 嗯,这只是我的意见.我不认为你应该按照你的建议去做,因为那样会使你的代码“多样化”(我的意思是,从演员模型中变成更具体的东西).从技术上讲,演员不应该共享任何州,而且他们应该只对事件(消息)做出反应.无论如何,使用for comprehension可以将上面的内容重写为:

for {
  room <- rooms
  id <- (room ? GetId).mapTo[Int]
  name <- (room ? GetName).mapTo[String]
} {
  println(id)
  println(name)
}

此外,您可以创建一条消息,将id和name作为元组返回,依此类推.可能性是无限的,但我不允许以这种方式直接访问甚至是不可变状态,因为它使我对编码进入应用程序的特定模式的视觉有点混乱.

点赞