Today we will discuss the Prototype pattern.
The creation of objects in an application can be configured by metadata, for example by using Dependency Injection containers, or programmatically, in the case that it is accomplished by writing code.
The most customizable option for programmatic creation is the Prototype pattern. This pattern consists in choosing an already existent object, with a clone() operation available, as the base for creating new objects of the same kind.
The Prototype pattern allows also:
- management of available instances at runtime, performed simply by adding and removing operations on a collection of cloneable objects.
- specification of new objects very similar to each other, by cloning an existing one and changing its properties using setters.
- specification of new objects at runtime; a GoF example is about a circuit design system which lets the user insert already defined circuits as blocks of a new one. The circuits implement a clone() operation which clones all the components recursively.
- Prototype: interface of the cloneable classes.
- ConcretePrototype: implements the clone operations (the ones which are not already supported by the language).
- Client: actually clones Prototype instances to use the clones as new objects.
- in languages where a Class object (meta programming) is available, the Prototype pattern is less important because Class objects are already standard prototypes. In Php, the most we can configure is a class name with a string, along with an array that represents a series of constructor options, so it can be considered as a practical solution.
- main problem is implementing a clone() method, which should produce copies or references to collaborators, a difference that should be decided case-by-case (deep or shallow copies); php has a standard clone operator and __clone() magic method which are used in the code sample; I suggest to refer to the sample and the manual for more information.
- after the cloning process, it is often suggested to add an initialize() method which allows for setting pieces of state which may differ from the prototype object; for instance, an id or a name field. This method should not be included in the Prototype interface or its parameters be put in the clone() method: first, php does not support cloning with parameters; second, different ConcretePrototypes will need different initialization values or no values at all.
Prototype seems a very simple pattern but this post turned out as detail-rich one. Do you feel anything is missing? Add a comment.