开发者

Composing actors

I've implemented a Listenable/Listener trait that can be added to Actors. I'm wondering if it's possible to attach this styl开发者_运维知识库e of trait to an actor without it having to explicitly call the listenerHandler method?

Also I was expecting to find this functionality in the Akka library. Am I missing something or is there some reason that Akka would not not include this?

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())
    }
}


Why not extend Actor directly, or if you want non-Actors to be Listenable also, create a ListenableActor that extends Actor with Listenable?

You then would override receive in Actor as you've done above (except you'd want to call super.receive also, wouldn't you?--you'd just want to modify the function that's passed in).


I suggest you extend Actor and use an abstract override.


Why haven't I seen this question before, erm, well, better late than never:

http://doc.akka.io/docs/akka/snapshot/scala/routing.html


Here is a solution (a modified version of the example from Beginning 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)
        }
    }
}


There is built-in support for this in Akka: https://github.com/jboner/akka/blob/release-1.2/akka-actor/src/main/scala/akka/routing/Listeners.scala

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜