When it comes to creating new objects dynamically, an application needs to able to instantiate and remove objects at run-time. This becomes particularly difficult if the concrete classes describe similar objects that only vary in representation, because you could end up with a lot of subclasses for basically the same kind of product. Enter the Prototype pattern!
This pattern introduces a radically new way of creating objects, namely by cloning a prototypical instance. This way it makes varying object properties easy. The book-definition of the pattern is “Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.” So use this pattern when
Now, it sounds fairly simple, but the implementation might seem a bit difficult at first. Let’s consider the following example: we have an application which creates forms with a varying number of fields, and different types of elements (say radio buttons and text inputs
). Since both of them define form elements, we can create an AbstractElement class for describing the basic structure of an element and then extend it and overwrite each object-specific operation. Similar to the Singleton pattern, a prototype manipulates its members by using setter and getter methods, and as Singleton creates references throughout the application to a single object using a static function, so does Prototype create new objects by cloning an existing object.
Now it’s type to start defining elements (or products). To do this we define two interfaces, one for elements, and one for “clonable” objects, to make it even more clear how this pattern is applied:
interface IElement { public function setName( $name ); public function setValue( $value ); public function getName(); public function getType(); public function getValue(); public function renderElement(); } interface IClonable { public function cloneSelf(); }
Nothing really fancy so far, except the fact that IElement is missing the setType() method. The reason for this is so that you won’t be able to clone a text input from a radio button and vice-versa, although technically you could (since in HTML input elements are created by specifying the ‘type’ attribute).
Now that we established what an element can and should do, it’s time to give it another dimension by defining the abstract class which we’ll be extending to define concrete elements (text and radio). It implements all the functions in the two interfaces defined above:
class AbstractElement implements IElement, IClonable { protected function setType( $type ) { $this->_type = $type; return $this; } public function setName( $name ) { $this->_name = $name; return $this; } public function setValue( $value ) { $this->_value = $value; return $this; } public function getName() { return $this->_name; } public function getType() { return $this->_type; } public function getValue() { return $this->_value; } public function renderElement() { echo '<input type="'.$this->getType().'" name="'.$this->getName().'" value="'.$this->getValue().'" />'; echo "<br />\r\n"; } public function cloneSelf() { $className = get_class( $this ); return new $className( "", "", $this ); } protected $_name = ""; protected $_type = ""; protected $_value = ""; }
The first three methods of the class replace the existing values of the member variables which define an element. But in addition to that, they also return a copy of the current object. This is called Method chaining and it’s useful for compacting code by calling multiple methods of an object on the same line (here is a link for more info). The getter methods just return the values of the objects member variables, obviously.
And the final method, the cloneSelf() function. We use this method to create new elements, first by getting their class and then calling the constructor. We pass the constructor three elements (the name, the value and the object to be cloned, which is the current object). Although it might not be clear why we need to pass the first two, think about it this way: we still need to have a prototype instantiated using new, and we need to pass it a name and a value; the third element however is used to pass a reference of the object to be cloned, and since each element clones itself, guess who the reference points to…That’s right, the very same object. This is not quite the typical way of implementing this pattern, since the book states that each concrete element should define the clone operation, in order to return an instance of the element’s class, but since we use the neat little get_class function, we can define just one method in the abstract class and it will work on all classes that extend it. However, this is language-specific, some programming languages might not support this feature.
Good so far, now we need some concrete objects so we can define form elements. Let’s start with the simpler one, TextElement, since it only needs a constructor. We need this to create a prototype for creating new clones:
class TextElement extends AbstractElement { public function __construct( $name, $value, AbstractElement $element = NULL ) { $this->setType( "text" )->setName( $name )->setValue( $value ); } }
Notice the way the setter methods are called. Method chaining really comes in handy.
The second element we’ll be creating is the RadioElement. We render it slightly differently than the TextElement, to illustrate the flexibility of this pattern, so we’ll need to overwrite the render() method:
class RadioElement extends AbstractElement { public function __construct( $name, $value, AbstractElement $element = NULL ) { $this->setType( "radio" )->setName( $name )->setValue( $value ); } public function renderElement() { echo '<input type="'.$this->getType().'" name="'.$this->getName().'" value="'.$this->getValue().'" />'.$this->getValue(); echo "<br />\r\n"; } }
So, the constructor is basically the same, exact it has a different type set. The renderElement() method however has been redefined to RadioElement objects are rendered in a slightly different way than TextElement objects.
Now we can take a look at how we can use these classes to create elements. Like we said earlier, we can create new items by cloning a prototype, so the first thing is to create a prototype, in order to have a template for creating new objects. We do this the standard way, using new:
$radio1 = new RadioElement( "input1", "1" ); $text1 = new TextElement( "text1", "foo" );
Now we have two prototypes, one for each type of element we can create. This creates an immediate problem, what do we do when we have a lot of prototypes and managing them becomes difficult. The most elegant solution would be to create a prototype manager, an object that stores prototypes and creates the appropriate objects according to requests. This however requires an implementation of your choice, so no example is provided for the manager.
The last thing we need to look at, is how new objects are created and rendered. This is where Method chaining really comes in handy. We could clone an object, set new properties and render it altogether on one single line, here’s how:
$radio1->renderElement(); $radio2 = $radio1->cloneSelf()->setName( "input2" )->setValue( "2" )->renderElement();
Focus on the $radio2 object. We first clone the prototype, which is $radio1, we then give it a name and a default value, and finally render it. So what’s the big deal, I hear you ask. Well, consider an object having more properties (perhaps referring to color, border etc.), it would be neat to be able to set all these parameters in one go. But why not use a single function? One reason would be because then you’d have to mind the orders of the parameters, to avoid this you could use an array, but there would still be the issue of creating it. Another reason would be because you’d have to parse through all the function arguments regardless of how many you want to set.
Hopefully, this was a useful article about the final creational pattern. A demo of the application is found here, and the source code here.