Factories and Components - laforge49/Asynchronous-Functional-Programming GitHub Wiki

An AsyncFP Factory is used to create and configure an Actor. And actors can use the factory method to access the factory which created them. Factories are useful for managing complex configuration requirements. And by removing configuration logic from an actor, modularity and code reuse are improved.

Here is a simple Factory subclass that provides a constant to the actors that it creates:

class ConstantFactory(_constant: Any)
  extends Factory(null) {

  def constant = _constant

  override protected def instantiate = new ConstantActor
}

case class Constant()

class ConstantActor
  extends Actor {

  bindMessageLogic(classOf[Constant], new ConcurrentData(
    Unit => {
      //factory is not initialized until after the actor is constructed.
      factory.asInstanceOf[ConstantFactory].constant
    }
  ))
}

FactoryTest

##Composite Actors

A composite actor is an aggregate of an Actor object and one or more Component objects. Composite actors are created using a Factory object. Here is a very simple Factory for creating a composite actor:

class CompositeFactory
  extends Factory(null) {

  include(new SC1Factory)
}

Composites created by this factory consist of an Actor object, the component created by SC1Factory, and other components as required. A different class can be used for the actor by overriding the instantiate method. And additional components can be added to the composite by adding multiple calls to the include method.

Here is the code for the SC1 component factory:

class SC1Factory
  extends ComponentFactory {

  addDependency(classOf[SC2Factory])
}

SC1Factory creates a Component object, which is included in the composite being created. But it also requires the inclusion of a component created by SC2Factory.

There can be any number of components in the same composite actor with the same or overlapping dependencies for other components, but the created composite will only contain a single instance of each type of component. (Where type in this case refers to the component factory.)

Here's the code for SC2Factory and the component it creates:

class SC2Factory
  extends ComponentFactory {

  override protected def instantiate(actor: Actor) = new SC2(actor)
}

case class DoIt()

class SC2(actor: Actor)
  extends Component(actor) {

  bind(classOf[DoIt], doit)

  def doit(msg: AnyRef, rf: Any => Unit) {
    println("Done it!")
    rf(null)
  }
}

SC2Factory just creates a SC2 component object, which is included in the composite being created. The SC2 object contributes the logic for processing DoIt messages. Putting it all together, the CompositeFactory defined above creates a composite actor from an Actor object, a Component object and a SC2 component object. And the composite so created can process DoIt messages.

DependenciesTest