SnapShooter Backups Server, Database, Application and Laravel Backups - Get fully protected with SnapShooter

Understanding Design Patterns - Factory Method

Define an interface for creating an object, but let the classes that implement the interface decide which class to instantiate. The Factory method lets a class defer instantiation to subclasses.

With Simple Factory in place, developers are now enjoying their day at Dragon Inc. Despite the thorough discussion of toys, we haven't really looked the toy classes yet. Toy is an abstract class with the functions prepare(),package(), and label().

abstract class Toy
{
    public $name  = '';
    public $price  = 0;
 
    public function prepare()
    {
        echo $this->name. ' is prepared';
    }
 
    public function package()
    {
        echo $this->name. ' is packaged';
    }
 
    public function label()
    {
        echo $this->name . ' is priced at '.$this->price;
    }
}

The concrete class Car and Helicopter inherit from super class Toy. They are pretty straightforward.

Car:

class Car extends Toy
{
    public $name  = 'Car';
    public $price = 20;
}

Helicopter:

class Helicopter extends Toy
{
    public $name  = 'Helicopter';
    public $price = 100;
}

Back to Dragon Inc. The CEO walks in to the developers' office with a smile on his face, but we know there's bad news coming. The CEO happily announces that Dragon Inc. is going to open several factories in US. They'll be located in different States, and the first two factories will be in New York and California. All toys will be produced locally with their own properties, which means that for the same type of toy Car, the ones produced in New York will be NyCar and those from California will be CaCar. Simple Factory will make this task a cinch for the development team. All they need to do is create a location specific SimpleFactory class and a location specific ToysFactory class. Simple Factory simplifies the task and makes the developers' job easy.

For example, for New York we could do:

class NySimpleFactory
{
 
    public function createToy($toyName)
    {
        $toy = null;
        if ('car'==$toyName) {
            $toy = new NyCar();
        } else if ('helicopter'==$toyName) {
            $toy = new NyHelicopter();
        }
        return $toy;
    }
}
 
class NyToysFactory
{
    public $simpleFactory;
 
    public function __construct(SimpleFactory $simpleFactory)
    {
        $this->simpleFactory = $simpleFactory;
    }
 
    public function produceToy($toyName)
    {
        $toy = null;
        $toy = $this->simpleFactory->createToy($toyName);
        $toy->prepare();
        $toy->package();
        $toy->label();
        return $toy;
    }
}

The developers finish the new code quickly and hand it over to the US factories. After two weeks, the phone starts ringing in the developers’ office because the New York factory was having production issues. It turns out that the NyToysFactory class has been modified by developer of the remote branch because staff there do not want to do packaging and labeling work. They have modified produceToy() function by removing label() and package() functions.

It seems like Simple Factory won't work in this scenario. We don't want branches in US to be able to modify produceToy() function. produceToy() should consist of a set of standard procedures and the branches should only be responsible for creating location specific toys. What if they can create an abstract class? And the abstract class they created will have a concrete produceToy() method which will implement a set of standard operating procedure that all branches have to follow. Inside the produceToy(), it calls its own abstract method createToy() to obtain a toy object. This way createToy() is able to encapsulate object creation and, since it's abstract, it delegates the creation to its subclasses.

That sounds like exactly what they need in their case:

abstract class ToysFactory
{
    public function produceToy($toyName)
    {
        $toy = null;
        $toy = $this->createToy($toyName);
        $toy->prepare();
        $toy->package();
        $toy->label();
        return $toy;
    }
 
    abstract public function createToy($toyName);
}

Now in New York branch, all they need to do is to implement createToy() method in the subclass:

class NyToysFactory extends ToysFactory
{
 
    public function createToy($toyName)
    {
        $toy = null;
        if ('car'==$toyName) {
            $toy = new NyCar();
        } else if ('helicopter'==$toyName) {
            $toy = new NyHelicopter();
        }
        return $toy;
    }
 
}

For the factory in California, they have to create another subclass CaToyFactory to produce toys locally:

class CaToysFactory extends ToysFactory
{
    public function createToy($toyName)
    {
        $toy = null;
        if ('car'==$toyName) {
            $toy = new CaCar();
        } else if ('helicopter'==$toyName) {
            $toy = new CaHelicopter();
        }
        return $toy;
    }
}

In the code above, function createToy() in ToysFactory class is called factory method. Factory Method pattern defines an interface(createToy) for creating an object. But it delegates the actual creation to subclasses(NyToysFactory and CaToyFactory). This way subclasses decide what object to create.

The end

Hopefully this simple tutorial helped you with your development. If you like our post, please follow us on Twitter and help spread the word. We need your support to continue. If you have questions or find our mistakes in above tutorial, do leave a comment below to let us know.