Pergunta
Eu implementei um traço de ouvinte/ouvinte que pode ser adicionado aos atores. Estou me perguntando se é possível anexar esse estilo de característica a um ator sem ter que chamar explicitamente o ouvinte método?
Além disso, eu esperava encontrar essa funcionalidade na biblioteca Akka. Estou perdendo alguma coisa ou há alguma razão para que Akka não inclua isso?
trait Listenable { this: Actor =>
private var listeners: List[Actor] = Nil
protected def listenerHandler: PartialFunction[Any, Unit] = {
case AddListener(who) => listeners = who :: listeners
}
protected def notifyListeners(event: Any) = {
listeners.foreach(_.send(event))
}
}
class SomeActor extends Actor with Listenable
{
def receive = listenerHandler orElse {
case Start => notifyListeners(Started())
case Stop => notifyListeners(Stopped())
}
}
Solução
Por que não se estender Actor
Diretamente, ou se você deseja que os não-atores também sejam ouvidos, crie um ouviceableActor que estende o ator com ouvido?
Você então substituiria receive
no ator como você fez acima (exceto que você gostaria de ligar super.receive
Além disso, não?-você só gostaria de modificar a função que foi passada).
Outras dicas
Eu sugiro que você estenda o ator e use um abstract override
.
Por que eu nunca vi essa pergunta antes, erm, bem, melhor tarde do que nunca:
Aqui está uma solução (uma versão modificada do exemplo do início do Scala):
import se.scalablesolutions.akka.actor.Actor
case class AddListener(who: Actor)
case class RemoveListener(who: Actor)
class ListenableActor extends Actor {
private var listeners: List[Actor] = Nil
def receive = {
case AddListener(who) => listeners ::= who
case RemoveListener(who) => listeners.filter(_ ne who)
}
protected def notifyListeners(event: Any) = {
listeners.foreach(_.send(event))
}
}
class ImplementingActor extends ListenableActor {
override def receive = {
super.receive orElse {
case Message(content) => println(content)
}
}
}
Há suporte embutido para isso em Akka: https://github.com/jboner/akka/blob/release-1.2/akka-actor/src/main/scala/akka/routing/listeners.scala