Posted on 18-01-2010
Filed Under (PHP) by Romi

Many might argue that this should be the first topic when learning design patterns, and they could be right, but I’m documenting them in cronological learning order. So here we are today discussing the Factory Method pattern, a very simple and useful way of designing the part of an application responsible for creating new objects.

The definition in the Design Patterns book is: “Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses“. So, in other words, we create an interface for a class that creates elements, and then implement it to create elements in a particular way. Now, let’s take a closer look at the implications of this pattern and it usefulness. If you have ever been in the situation when you need to create different types of objects, but the means for creation alter the context of the application where the objects are created, then you will love this pattern. It unifies the way objects are created so you can add new types without having to alter the main code of the application where the objects are used. Talk about cool, this pattern is awesome!

Now, that we have a basic idea regarding what is for, it’s time to take a look at how it works and how to implement it. Again, a boring forms example, but in a way, I must admit I want to keep it this way, for consistency. So, we’ll creating several different objects by using a single interface, and without altering the code for instantiating different types of objects (which in this case are form elements… again). That being said, we can take our first look at the abstract class for creating objects, namely AbstractFactory:

class AbstractFactory
{
    public function getNewElement( $type, $name = "", $value = "" )
    {
        $this->_type    = $type;
 
        $element = $this->createElement( $name, $value );
    }
 
    protected function createElement( $name = "", $value = "" ) {}
 
    protected $_type;
}

Pretty simple, but very effective, you’ll see. Let’s look at it more closely. First, the getNewElement() function, which is used for creating an element with a specific type, and then rendering it. The protected function createElement() is empty because it will be defined by the subclasses created by extending this class, we just need to declare it here so that the pattern will be easier to understand. In PHP, defining this function in the abstract class is optional, however I don’t think this applies to other languages. As you can see, the getNewElement() function calls createElement() to create a local object and then return it. Here is the core of the pattern, but to make it even more clear, let’s see what a concrete factory class looks like:

class OptionFactory extends AbstractFactory
{
    protected function createElement( $name = "", $value = "" )
    {
        switch( $this->_type )
        {
            case "checkbox":
                return new CheckElement( $name, $value );
 
            default:
                return new RadioElement( $name, $value );
        }
    }
}

I have named it OptionFactory because it creates two types of objects, checkboxes and radiobuttons (the other example is called ValueFactory, and it deals with creating text inputs and buttons, just like this one, except it returns other types of objects). So as you can see, the subclass only (re)defines the createElement() function and returns an object depending on the the $_type member variable. Notice that we don’t have the getNewElement() function, since we don’t need to overwrite it, and that’s what the definition of this patter is reffering to when stating “let subclasses decide which class to instantiate“. I won’t be insisting on the …Element classes, because they are mostly the same as the ones from previous posts and our main focus is the pattern itself. Now that we took care of the abstract and concrete factories, we look at the final aspect of the pattern, the interface which creates different objects in the same way. The simplest way to illustrate this is by defining a function which takes an Factory parameter, but which is an instantiated concrete factory:

function createAndRenderElement( AbstractFactory $factory, $type, $name = "", $value = "" )
{
    $element = $factory->getNewElement( $type, $name, $value );
    $element->render();
}

All done! Now we can create (and render) different objects by using the same function, AND we can add new elements with a corresponding factory class, without altering this function at all, AND… we still have access to the instantiated element object. Neat!

As always, to see this pattern in action, here is a little demo of creating multiple elements, so it rates poorly on interactivity, but here is the source code if you want to get your hands on the whole pie and maybe mess around with it.

(0) Comments    Read More   
Post a Comment
Name:
Email:
Website:
Comments: