Skip to content

Component Factories

laforge49 edited this page Oct 28, 2011 · 6 revisions

The order in which the components of an actor are instantiated becomes important when you have components which depend on other components. This is addressed by the ComponentFactory's addDependency function and the Actor's component function. For example, you might have a component, SaverComponent, which support a get and set on a value and another component, DoubleComponent, which directly accesses the value held by SaverComponent.

Let's start by looking at the Saver component and its factory.

case class Set(value: Int)
case class Get()

class SaverComponentFactory extends ComponentFactory {
  override def instantiate(actor: Actor) = new SaverComponent(actor)
}

class SaverComponent(actor: Actor) extends Component(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 SaverComponentFactory simply creates the component, as this component does not depend on any other component. Now let's look at the Double component and its factory.

case class Times2()

class DoubleComponentFactory extends ComponentFactory {
  addDependency(classOf[SaverComponentFactory])

  override def instantiate(actor: Actor) = new DoubleComponent(actor)
}

class DoubleComponent(actor: Actor) extends Component(actor) {
  val saver = actor.component(classOf[SaverComponentFactory]).asInstanceOf[SaverComponent]

  bind(classOf[Times2], doubleFunc)
  private def doubleFunc(msg: AnyRef, rf: Any => Unit) {
    saver.i *= 2
    rf(null)
  }
}

The Double component factory establishes the dependency on the Saver component by calling the addDependency function. This function takes one parameter, the Saver component factory class. The Double component can then safely call the component function on actor to get the component it depends on. The component function takes the same type of parameter as the addDependency funtion--the class of the Saver component factory.

Now what makes all this work is the Factory include function. This function is passed a component factory with which it creates the other required component factories, recursively. The component factories are then used to create the components in the correct order. This is illustrated by the Double factory, which includes the Double component factory.

class DoubleFactory extends Factory(null) {
  include(new DoubleComponentFactory)
}

Here then is the test code.

val doubleFactory = new DoubleFactory
val double = doubleFactory.newActor(new ReactorMailbox)
Future(double, Set(21))
Future(double, Times2())
println(Future(double, Get()))

And here is the output.

42

CompositeTest

Tutorial

Clone this wiki locally