Factory Method Design Pattern
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses. (dofactory)
- Product defines the interface of objects the factory method creates
- ConcreteProduct implements the Product interface
- Creator declares the factory method, which returns an object of type Product. Creator may also define a default implementation of the factory method that returns a default ConcreteProduct object. Creator may call the factory method to create a Product object.
- ConcreteCreator overrides the factory method to return an instance of a ConcreteProduct.
- When a class can not anticipate the type of the objects it is supposed to create. In other words, when a client does not know what concrete classes it will be required to create at runtime, but just wants to get a class that will do the job. If the classes doesn't extend common base class or interface they can not be used in a factory design template.
- When a class wants its subclasses to be the ones to specific the type of a newly created object.
- The creation of an object precludes its reuse without significant duplication of code.
- The creation of an object requires access to information or resources that should not be contained within the composing class
- The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application
- Lets a class defer instantiation to subclasses.
- Makes a design more customizable and only a little more complicated.
- The advantage of a Factory Method is that it can return the same instance multiple times, or can return a subclass rather than an object of that exact type.
- The main reason for which the factory pattern is used is that it introduces a separation between the application and a family of classes (it introduces weak coupling instead of tight coupling hiding concrete classes from the application). It provides a simple way of extending the family of products with minor changes in application code.
- Some Factory Method advocates recommend that as a matter of language design (or failing that, as a matter of style) absolutely all constructors should be private or protected. It’s no one else’s business whether a class manufactures a new object or recycles an old one.
- The new operator considered harmful. There is a difference between requesting an object and creating one. The new operator always creates an object, and fails to encapsulate object creation. A Factory Method enforces that encapsulation, and allows an object to be requested without inextricable coupling to the act of creation.
- The factory has to be used for a family of objects. If the classes does not extend common base class or interface they can not be used in a factory design template. If we do extend the class (e.g., by making the constructor protected—this is risky but feasible), the subclass must provide its own re-implementation of all factory methods with exactly the same signatures.
- Refactoring an existing class to use factories breaks existing clients.
- It might be overcomplicated.
- Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.
- Factory Method pattern uses inheritance and relies on a subclass to handle the desired object instantiation.with the Abstract Factory pattern, a class delegates the responsibility of object instantiation to another object via composition
- Factory Methods are usually called within Template Methods.
- Factory Method 'creation' is through inheritance and Prototype creation is through delegation.
- Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
- Prototype does not require subclassing, but it does require an Initialize operation. Factory Method requires subclassing, but does not require Initialize.