我剛開始學習Akka/Scala,並且我寫了一個小型聊天服務器。在akka/scala中訪問演員之外的不可變成員
想象一下,這是一個基於房間的聊天服務器,每個人都可以創建自己的房間,並且可以同時在幾個房間裏。每當房間內的會員用完時,房間就會關閉。房間由id: Int
標識,並具有不可變的name: 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")
}
}
好了,好了,它的工作原理...但是...在那裏爲我訪問一個演員裏面那些一成不變會員更方便地什麼辦法?我試圖讓一個包裝供房的演員,像下面的代碼:
case class RoomWrapper(val id: Int, val name: String, actor: ActorRef)
似乎不錯,但有一個問題:現在我不得不到處傳遞RoomWrapper
對象。當房間被毀壞時我怎樣才能得到通知?我不能context.watch
a RoomWrapper
!
如何解決這個問題?有沒有可能讓我這樣寫?
val rooms: List[ActorRef]
rooms map { room =>
println(room.id)
println(room.name)
}
這樣做反過來呢? 'Actor'中的'case class ImmutableRoomData(id:Int,name:String)',然後你只需要檢索一次,就可以避免'zip'。此外,地圖序列組合可以寫得更簡潔,如「遍歷」。 – lmm
@Imm我認爲ImmutableRoomData的想法基本上與提到的一個kaktusito元組相同,但「遍歷函數」是一個非常好的點!我應該使用它! –