It’s been a while since we’ve looked at designed patterns, so let’s continue our journey of design pattern adventures by looking at the Factory pattern.

What is it and why use it?

One of the larger problems in software development is tight coupling of system components. It is a problem, because:

  • it makes it harder to test components - we have to worry about constructing large pieces of the component, managing dependencies, creating test cases
  • it makes it difficult to swap certain components for others - for instance, say we’ve been using SQLLite database when the system was small. Now it got much larger than you anticipated and you need to migrate to another database (say Oracle, PostgreSQL, MySQL or any other). If we’ve done a bad job and coupled everything tightly - we would need do to a lot of work and change many things. On the other hand, if we’re lucky - it may need changes only in a few places.

Factory design pattern is a creational design pattern, that takes over and abstracts creation of objects. Basically, instead of creating objects with a new keyword, one asks the factory to create that object and that’s pretty much it.

It may seem that it only adds unnecessary overhead, however it does have advantages:

  • often certain information or resources, which should not exist within a user class, are required in order to create an object. Factory pattern helps to hide and manage dependencies and without tasking the user class to handle it
  • it helps to reduce code duplication - complex object initialization can be kept in one place (Keep it DRY - Don’t Repeat Yourself)
  • makes testing easier - factory methods can be overridden to return objects that are needed for testing

Code examples

It may be difficult to understand how it works, so let’s come up with an example.

Let’s say we have a game board that can have many players on it. Each player has it’s own name and coordinates (x, y). After creating players we want to run the game and see where players are.

<?php

/**
 * Let's say we have a game board that can have many players on it. Each player
 * has it's own name and coordinates (x, y).
 * After creating players we want to run the game and see where players are.
 */

class Player {
    public function __construct($name, $x, $y) {
        $this->name = $name;
        $this->x = $x;
        $this->y = $y;
    }

    public function getName() {
        return $this->name;
    }

    public function getPosX() {
        return $this->x;
    }

    public function getPosY() {
        return $this->y;
    }
}

class GameBoard {
    public function __construct() {
        $this->players = array();
    }

    public function registerPlayer(Player $player) {
        $this->players[] = $player;
    }

    public function run() {
        foreach ($this->players as $player) {
            printf(
                    "%s is on (%d, %d)\n",
                    $player->getName(),
                    $player->getPosX(),
                    $player->getPosY()
                  );
        }
    }
}

class GameFactory {
    private static $gameBoard;

    public static function createBoard() {
        if (!GameFactory::$gameBoard) {
            GameFactory::$gameBoard = new GameBoard();
        }
        return GameFactory::$gameBoard;
    }

    public static function createPlayer($name, $x, $y) {
        $player = new Player($name, $x, $y);
        GameFactory::$gameBoard->registerPlayer($player);
        return $player;
    }
}

// Create and run our game
$board = GameFactory::createBoard();
$jim = GameFactory::createPlayer("Jim", 1, 0);
$bob = GameFactory::createPlayer("Bob", 10, 7);
$board->run();
?>

So as you can see we are hiding how players are registered to the board. Client classes don’t need to know about the game board anymore - they only need to pass the data to the GameFactory and the object will be created. But now we can easily add different types of players (e.g. guests, administrators, registered users) if needed.

Though it may not be a good idea to always register players to a board as they may need to be not on it, but for the sake of the example that’s our “difficult object initialization”.

Last thoughts

Factory design pattern is one of the most used design patterns and it helps to solve certain software design problems, however as Fred Brooks said “There is no silver bullet”. If used incorrectly, Factory Design pattern may cause problems (e.g. increase in coupling between classes or components).

The code I used for this post and other posts about design patterns (Singleton, Observer) can be found in my repository on Github flakas/Design-patterns.

For further reading I suggest you these links: