Names and Factories - laforge49/Asynchronous-Functional-Programming GitHub Wiki
Names are important, especially when working with remote servers and persistence. Two types of names are supported: ActorId and FactoryId.
The Actor class has functions for accessing the factory and its id. But not every actor has a factory. And not every Factory has an id.
def factory: Factory
def factoryId: FactoryId
Actors which implement the IdTrait may optionally have an id as well; IdActory provides methods for accessing the ActorId.
def id: ActorId
def id(id: ActorId)
###Factories
Factory classes are responsible for instantiating an actor and for providing configuration data. Factories are especially useful when there are multiple actors of the same class which are configured differently. OK, lets look at an example.
abstract class UserFactory(id: FactoryId) extends Factory(id) {
def accountName: String
override protected def instantiate = {
val actor = new UserActor
actor
}
}
The UserFactory class is a Factory class for configuring and creating instances of class UserActor.
class FredFactory extends UserFactory(FactoryId("Fred")) {
override def accountName = "fredforall"
}
The FredFactory class has a factory id of Fred and creates an instance of class UserActor with an account name of fredforall.
case class AccountName()
class UserActor extends Actor {
bind(classOf[AccountName], accountName)
private def accountName(msg: AnyRef, rf: Any => Unit) {
rf(factory.asInstanceOf[UserFactory].accountName)
}
}
The UserActor class is an Actor which responds to an AccountName message by returning the account name in its factory. As a singleton, UserActor is also assigned an id derived from the id of its factory.
val fred = (new FredFactory).newActor(null)
println("account name = " + Future(fred, AccountName()))
As a test, we create a user and print the account name.
account name = fredforall
It is unwise to modify the configuration data of a factory after creating an actor, as it violates thread safty.