Factory injection
This article publishes a draft of a previously unreleased object-oriented design pattern |
The Factory injection design pattern provides a way to create objects of any generalized or concrete type, where the concrete type and the initialization of the created object is choosen by a context. Factory injection is a defused (or lightweight) form of inversion of control and similar to dependency injection, but does not inject each and every individual dependency into a dependent object (a client). Instead an injecting object (an injector, usually part of a framework) injects into the client those objects (factories) which create (or at least retrieve from a context) the dependencies on the clients request.
The client uses the factories with their common abstract type, but has no dependency to the concrete implementing types of these factories. The injector chooses the concrete implementations of the factories by an initially determined (static) context, e.g. to exchange the implementations of the factories by switching the context.
On the clients request, the factories can create objects by themselves and work similar to the abstract factory pattern, but they can also retrieve objects from other parts of the creational framework where the instances are created (e.g. based on the frameworks configuration) or referenced by a scoped object to manage their lifetime. The concrete factories should extend abstract factory types which are segregated by the type of object they create, in particular if they create objects by themselves or if they just retrieve objects from the framework.
A concrete factory creates or retrieves the concrete type of an object requested by the client with its abstract type (choosen according to the context that factory is assigned to). This way, the concrete type of such an object can be exchanged by switching the context.
In comparison to dependency injection, factory injection provides the same benefit in terms of exchanging implementations of dependencies by switching a context, but requires just a fraction of the efforts spent on configurations or definitions of the dependencies and changes thereof. Moreover, the impact and footprint on the client is way smaller, and still much smaller when the dependency to a factory is generalized and inherited. Maybe the greatest advantage of factory injection over dependency injection is the creation of stateful objects by the factories themselves, which allows to exchange the implementation of a (domain driven) business object - and hence allows for a richer domain model.
A client may request an object from a factory by different critera, depending on the type of factory. The client may just specify the object type, but may also specify further criteria the factory has to consider for the creation of the object. A factory which is specialized for a certain object type is queried with other arguments than the object type. For instance a factory which is specialized for creating or retrieving data access objects (DAO) can be queried with the entity type the DAO instance (that shall be returned) is taking care of. In that example the client got a DAO factory injected, calls that DAO factory passing the entity type to that factory and the factory returns the DAO instance that is responsible for the given entity type, but as a generalized DAO type. The client can then operate on that DAO as if it were injected directly into the client.
Factory injection can also be applied on top of a dependency injection framework which is already in use and the injected factories can then make use of that framework to retrieve (stateless) objects of certain types. This way an applied dependency injection can be migrated to an applied factory injection smoothly and gradually without having to exchange the framework in use itself.
Seiten |