Architecture:MediaWiki/factory pattern


The factory pattern describes objects that are used primarily to instantiate objects of another type. Factories should generally be stateless service objects. They are often used to encapsulate knowledge about the concrete type of the object and about the parameters to be passed to the constructor. Formally, factories can be understood as an object oriented approach to partial application of constructors.

As a rule of thumb, objects that are not service objects, but use service objects, should be constructed by a factory of some kind. In this way, factories enable Dependency Injection.

Factory objects typically have one or more factory methods that can be used to instantiate objects of the desired type. Factory methods typically have names staring with "new" or "get". If the name starts with "new", the method should guarantee that a fresh instance is returned every time. If the name starts with "get", the same instance may be returned multiple times. Factory methods typically take parameters, but they don't have to.

Some special kinds of factories can be identified based on the behavior of their factory methods:

  • If objects instantiated by the factory share a specific type, the factory can be thought of as homogeneous. This is the most common case, often used to aid Dependency Injection. A notable example of factories that are not homogeneous are service containers themselves, which return a different type of object from each factory method.
  • If the concrete type of the object instantiated by a factory method varies based on the parameters given, the factory can be thought of as dispatching, providing a form of polymorphism for the construction of objects. A notable example of this are registry services.

When grouping multiple factory methods into a single factory service, all objects created by a given factory should belong to the same domain, and they have similar dependencies. If a factory service ends up depending on a lot of different services, it may need to be split up.

Instantiation:
Factories are typically obtained from a service container, or from a higher level factory. They are themselves a dependency injection mechanism, and should not be instantiated directly.

Naming Convention:
Factories typically use the suffix "Factory" in the name. The name often starts with the type of object constructed by the factory - so a factory for User objects would be called UserFactory.

Layer constraint:
Factories are used across all layers.

Status:
As of July 2020, the output factory pattern is well established, and used increasingly to support Dependency Injection.

Examples:
Good examples of factories used to support dependency injection are ParserFactory and LinkBatchFactory.