Monday, January 11, 2010

Practical Php Patterns: Factory Method

This is the third post from the Practical Php Pattern series, which will touch the majority of the known design patterns, with a special look at their application in a php context and code samples.

The third creational pattern we will study is the Factory Method one.
By definition a Factory Method is any method whose responsibility is creating an object, or providing a already existent instance of a particular class.
Factory Methods are the seams which allow tuning of an instantiation; for example, to recycle already created objects or to introduce subclasses of the original Product.

ConcreteCreators, subclasses of a Creator class, redefine the factory method forcing it to create a ConcreteProduct instead of a generic Product. The subclass term is used here extensively, also to indicate an interface's implementations; the Creator nickname shows that the role of the class in this pattern is creating the Product, but by no means its responsibility consists in creating it: the responsibility of Creator is to accomplish some tasks which requires fresh instances of Product to be created, as a side effect. The responsibility of actually instantiating a ConcreteProduct is usually left to the ConcreteCreators.
This pattern has a strong affinity with the Abstract Factory one: usually every relevant method of the Abstract Factory is a Factory Method, but isolated Factory Methods can be used also in other situations. For instance, with the intention of having them overridden by subclasses, incorporating the factory in the class itself and having them called by Template Methods.
Factory Methods may be moved out of their class in subsequent refactorings and evolve in an external Abstract Factory.

PARTICIPANTS:
  • Product: the abstraction of the created object.
  • ConcreteProduct: a subclass or implementation of Product.
  • Creator: the base class, which declares an abstract or default Factory Method.
  • ConcreteCreator: a subclass of the Creator which overrides the Factory Method to return a ConcreteProduct.
The code sample reprises the Abstract Factory example and implements the same functionality using only a simple Factory Method. The disadvantage is that subclassing is required to take advantage of this hook.
<?php
/**
 * SECTION 1: a WidgetHelper interface and two different implementations.
 *
 * This class purpose is to generate blinking text in spite of all
 * usability recommendations. This is the Product.
 * As always, interfaces in php may be omitted.
 */
interface WidgetHelper
{
    /**
     * @return string
     */
    public function generateHtml($text);
}

/**
 * Implementation that generates html tied to a javascript library.
 * This is one ConcreteProduct.
 */
class JavascriptWidgetHelper implements WidgetHelper
{
    public function generateHtml($text)
    {
        return '<div dojoType="...">' . $text . '</div>';
    }
}

/**
 * Implementation that generates html that loads a flash object.
 * This is one ConcreteProduct.
 */
class FlashWidgetHelper implements WidgetHelper
{
    public function generateHtml($text)
    {
        return '<object>
        <param name="text">' . $text . '</param>
        </object>';
    }
}

/**
 * SECTION 2: a Creator class which defines a seam to change the object it
 * creates during execution.
 *
 * Normally we would inject the chosen WidgetHelper to the Client class, but
 * since WidgetHelpers are created during the execution (basing on business
 * logic) we cannot instantiate them in advance and so we need an abstraction
 * on the creation process to allow reusing and overriding: the Factory Method
 * createWidgetHelper().
 */
abstract class LoginPage
{
    /**
     * @return WidgetHelper
     */
    public abstract function createWidgetHelper();

    /**
     * A Template Method which uses the Factory Method.
     */
    public function render()
    {
        $userId = uniqid('User ');
        // insert all the logic needed here...
        if (true or $complexBusinessLogicRules) {
            $helper = $this->createWidgetHelper();
            return $helper->generateHtml("Welcome, $userId");
        }
    }
}

/**
 * First subclass: creates Javascript-based helpers.
 * This is one ConcreteCreator.
 */
class JavascriptLoginPage extends LoginPage
{
    public function createWidgetHelper()
    {
        return new JavascriptWidgetHelper();
    }
}

/**
 * Second subclass: creates Flash-based helpers.
 * This is one ConcreteCreator.
 */
class FlashLoginPage extends LoginPage
{
    public function createWidgetHelper()
    {
        return new FlashWidgetHelper();
    }
}

$page = new FlashLoginPage();
echo $page->render(), "\n";
$page = new JavascriptLoginPage();
echo $page->render(), "\n";
The testability of code that follows this pattern is still nearly good as with an Abstract Factory; all it takes to mock the creation process is to subclass and override the factory method, which we would do anyway in the test suite with an external ConcreteFactory class and is a standard testing technique.
A common misconception is a static version of the Factory Method, which is placed on a Product or ConcreteProduct class and provide a constructor with a fancy name. The original intent was having the method overridden, so if it is implemented as static the goal is not achieved; the trick is that the method should reside on the class that need the instantiation of Product objects, and not on the Product itself.
Some versions even propose to maintain a static object pool managed by a static method in the Product class, which is dangerously-equivalent to filling some water bottles with gasoline and amassing them in the car trunk just in case the tank needs to be refilled, throw in a burning match and closing the trunk with the keys inside.
Moreover, if the method has references to the subclasses of Product, they become all mutually coupled and depend the one on all the others, forcing to modify the base class in case a new subclass is added.
In conclusion, a Factory Method is a non-static overridable creation method, which belongs to the class that needs to instantiate a Product (or to a class composed by it).

Remember to comment and propose patterns for inclusion in this series!

5 comments:

romanb said...

A static factory method is pretty much unrelated to the concept of the classic factory method pattern, so I'm not sure why you're mentioning it here as a misconception.

Static factory methods are a direct alternative to the "new" operator that provide many advantages, like:

1) Unlike constructors, they have names.

2) They're not required to create a new object each time they're invoked. This is a huge advantage. Instance pooling, especially of immutable objects, can be extremely useful. See the Flyweight pattern which can be implemented this way.

3) Unlike constructors, they can return an instance of a subtype. Thus you can return a different implementation without affecting clients.

As far as testability is concerned, since it is in direct comparison to the "new" operator, there is no difference. "foo = new Foo(args)" is just as hard to mock as "foo = Foo.some(args)".

I am certainly no fan of "static" but static factory methods are one of the rare cases where I still find them acceptable.

Giorgio said...

Because during research I found out that people mixes the design pattern and the static factory method:
http://sourcemaking.com/design_patterns/factory_method
"An increasingly popular definition of factory method is: a static method of a class that returns an object of that class’ type. But unlike a constructor, the actual object it returns might be an instance of a subclass."
Note that the page is titled "Factory Method Design Pattern" and it's in the top 10 results of Google. It contains Uml diagrams for the classic GoF pattern.

The immutable "newable" objects case is a nice example of a correct usage that I did not think of. :)
Though, I do not agree on the subclasses advantage, because I prefer not to refer to subclasses from a superclass (avoiding a mutual dependency between them).

Anonymous said...

Hi Giorgio, what do you think of the examples found at wikipedia http://en.wikipedia.org/wiki/Factory_method_pattern#PHP
here they define an abstractProduct but abstractCreator and have different concrete creators with a factory method returning the concrete product.
Is this actually a good example of a factory method. I am often implementing them like this!

Cheers, keep up the good writing

Giorgio said...

The article on Wikipedia has a Uml diagram on top which corresponds to the classic pattern, but in the code samples it describes static creation methods. Since there is an interface for the creation methods, it makes no sense to make it static *in this pattern* (interfaces cannot contain static methods). In fact in the talk page:
http://en.wikipedia.org/wiki/Talk:Factory_method_pattern
there is a section "Article doesn't really describe the GoF pattern?"

Template Design said...

Nice presentation!I truly enjoy the way you explorer your experience and knowledge about the subject...Its been really helpful post for the developers as well as me.Cheers for this great sharing...

ShareThis