Now that we have looked at the Factory Method pattern, which delegates the responsibility, of deciding which objects to create, to its subclasses, we’ll be analyzing the Abstract Factory pattern, which is used for created multiple objects from the same family, by providing a common interface for creation. In the words of the Gang of Four (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides), the pattern’s main intent is to “provide an interface for creating families of related or dependent objects without specifying their concrete classes.”
Like all other patterns (not just creational, but behavioural and structural as well), Abstract Factory is applied in a specific situation. Here are a few examples:
So, this pattern comes in handy when you need an easy way for creating families of related objects by using a single interface and you need to enforce some rules regarding relationships between objects. Now, for the actual example, let’s consider the following situation: you want to create a form with text inputs, or radio buttons (of course, each of them with a specific submit button). We’ll need to create a class for creating text inputs, along with the corresponding submit button, and the same for the class responsible for creating radio buttons.
First thing’s first, we need to create the Factory interface, IFactory:
interface IFactory { public function createInput(); public function createSubmit(); }
And that’s that, a function for the input, and one for the submit button, so we can alternate between concrete factories, and speaking of which, let’s take a look at out first concrete factory, the OptionFactory class, which creates radio buttons:
class OptionFactory implements IFactory { public function __construct() {} public function createInput( $name = "", $value = "" ) { return new RadioElement( $name, $value ); } public function createSubmit( $name = "", $value = "" ) { return new SubmitElement( $name, $value.' (Option)' ); } }
Now, before explaining it, it’s best we take a look at the other concrete factory, meaning the ValueFactory class, which creates text inputs:
class ValueFactory implements IFactory { public function __construct() {} public function createInput( $name = "", $value = "" ) { return new TextElement( $name, $value ); } public function createSubmit( $name = "", $value = "" ) { return new SubmitElement( $name, $value.' (Value)' ); } }
As you can see, there are only a few differences between them, the most important one being in the createInput() function, since the two of them return a different type of object. This is not true in the other case. The createSubmit() function returns an element of the same class in both cases, but it passes to the element constructor a different value, only to distinguish better the relationship between the objects created by a specific class of factories. As usual, the Element classes of the application stay the same from the previous version, so I won’t explain them here. But I will insist on the following part, which is the main interface for creating the objects. To keep it simple, I have written a function which creates a form with elements based on the type of factory passed as an argument to it. The argument has the type IFactory, so this way we can pass it a OptionFactory and ValueFactory object and it will create and render the appropriate form. Here is what it looks like:
function createForm( IFactory $factory ) { $element1 = $factory->createInput( "factoryInput", "Option Factory" ); $element2 = $factory->createInput( "factoryInput", "Value Factory" ); $submit = $factory->createSubmit( "factorySubmit", "Create elements" ); $element1->render(); $element2->render(); $submit->render(); }
So, this function can take a concrete factory as a parameter and instantiate the corresponding objects, before rendering them. Now the only thing left is to apply it and see how it performs. We add a basic form to our index.php and call the createForm() function with the appropriate factory, based on the value of $_POST["factoryInput"]:
<form method="post"> <?php switch( $_POST['factoryInput'] ) { case 'Value Factory': createForm( new ValueFactory ); break; default: createForm( new OptionFactory ); break; } ?> </form>
And there we have it! Of course, maybe it would have been even more intuitive if I added more types of elements to each factory, but I leave that to you so you can play around with the code, which can be found here. You can give the demo a go here too.