Components - laforge49/Asynchronous-Functional-Programming GitHub Wiki
Components are used to extend the capabilities of Actors. For example, if we have an actor which implements getter/setter message processing, it is easy to add a component which doubles the value held by the actor.
The code for getting and setting a value is pretty straight forward.
case class Set(value: Int)
case class Get()
class Saver extends Actor {
var i = 0
bind(classOf[Set], setFunc)
private def setFunc(msg: AnyRef, rf: Any => Unit) {
i = msg.asInstanceOf[Set].value
rf(null)
}
bind(classOf[Get], getFunc)
private def getFunc(msg: AnyRef, rf: Any => Unit) {
rf(i)
}
}
The code for the component which will double the value is similar.
case class Times2()
class DoubleComponent(saver: Saver) extends Component(saver) {
bind(classOf[Times2], doubleFunc)
private def doubleFunc(msg: AnyRef, rf: Any => Unit) {
saver.i *= 2
rf(null)
}
}
Aggregating an actor with one or more components is easily done with a Factory class.
class DoubleFactory extends Factory(null) {
override protected def instantiate = {
val saver = new Saver
val doubleComponent = new DoubleComponent(saver)
addComponent(doubleComponent)
saver
}
}
The test code is also straight forward.
val doubleFactory = new DoubleFactory
val double = doubleFactory.newActor(new ReactorMailbox)
Future(double, Set(21))
Future(double, Times2())
println(Future(double, Get()))
And here's the output.
42