14 diciembre 2008

Factories

Factories
Entities and Aggregates can often be large and complex – too complex to create in the constructor of the root entity.

When a client object wants to create another object, it calls its constructor and possibly passes some parameters. But when the object construction is a laborious process, creating the object involves a lot of knowledge about the internal structure of the object, about the relationships between the objects contained, and the rules applied to them.

Factories are used to encapsulate the knowledge necessary for object creation, and they are especially useful to create Aggregates. When the root of the Aggregate is created, all the objects contained by the Aggregate are created along with it, and all the invariants are enforced.

It is important for the creation process to be atomic. If it is not, there is a chance for the creation process to be half done for some objects, leaving them in an undefined state. This is even more true for Aggregates. When the root is created, it is necessary that all objects subject to invariants are created too.
Otherwise the invariants cannot be enforced. For immutable Value Objects it means that all attributes are initialized to their valid state. If an object cannot be created properly, an exception should be raised, making sure that an invalid value is not returned.

Therefore, shift the responsibility for creating instances of complex objects and Aggregates to a separate object, which may itself have no responsibility in the domain model but is still part
of the domain design. Provide an interface that encapsulates all complex assembly and that does not require the client to reference the concrete classes of the objects being instantiated.
Create entire Aggregates as a unit, enforcing their invariants.
There are several design patterns used to implement Factories.
The book Design Patterns by Gamma et all. describes them in detail, and presents these two patterns among others:
  • Factory Method
  • Abstract Factory
There are times when a Factory is not needed, and a simple
constructor is enough. Use a constructor when:
  • The construction is not complicated.
  • The creation of an object does not involve the creation of others, and all the attributes needed are passed via the constructor.
  • The client is interested in the implementation, perhaps wants to choose the Strategy used.
  • The class is the type. There is no hierarchy involved, so no need to choose between a list of concrete implementations.

No hay comentarios: