Mar 19, 2014
Table of contents:
In software development there are many widely recognised, reusable solutions to commonly occurring problems. Being able to recognise these reusable solutions allows you be able to pick up new code much quicker because you will intuitively understand what the developer was trying to accomplish and how the code works.
One of the most common reusable solutions is known as the Factory Method Design Pattern.
In this article I’m going to be looking at the Factory Method Design Pattern, explaining exactly what it is, how it works and when you should use it.
As usual, the following code examples are in PHP, but the pattern is applicable to many different programming languages. One of the beautiful things about learning commonly recognised patterns is they are usually applicable to many different languages.
The Factory Method Design Pattern is where you create a class (the factory) which has the sole responsibility of creating other classes.
For example, imagine our application can share data with many popular social applications. Each of these social applications should have their own class which includes specific methods and properties that are relevant to only that specific social application:
class Twitter
{
public function share()
{
return $this->tweet();
}
}
class Facebook
{
public function share()
{
return $this->post();
}
}
We can use a Factory class to control the creation of these classes:
class Factory
{
public static function create($name)
{
if (class_exists($name)) {
return new $name();
}
}
}
$twitter = Factory::create("Twitter");
$facebook = Factory::create("Facebook");
Now that we have the Factory class we can control which specific social sharing class the application chooses at runtime by simply specifying the name of the class as an argument.
So you might be thinking, what is the benefit in using a Factory?.
There are basically three benefits in using this pattern.
Firstly, using a Factory ensures that we keep our code DRY. So instead of having many different ways to instantiate our social sharing classes, using a Factory ensures that we have a single representation of that action within our code.
This is even more important if the creation of these objects is or becomes complicated.
For example, say we also needed to pass the class some configuration options or user data. Using a Factory we can keep all of this logic in one place, rather than repeating it wherever we need an instance of the social class:
class Factory
{
public static function create($name, $config)
{
if (class_exists($name)) {
return new $name($config);
}
}
}
The second benefit of the Factory pattern is it allows you have a clean separation of concerns.
If you look back at the Twitter
and Facebook
classes, you will notice that they both have a single share
method. The Twitter
class uses the share method to send a tweet, and the Facebook
class uses the share method to create a new post.
This kind of implementation detail is only the concern of the specific class, the overall system does not care whether it is a tweet or a post, it only cares about the actual action of sharing.
So by using a Factory class to create the social application class. We can share from our application without ever knowing the actual implementation details of how the data is shared. This implementation detail should not be contained within the Factory.
And finally, the lifetime management of the object should be centralised. So instead of having different ways the social classes can be instantiated throughout our codebase, the Factory Method ensures that creating new objects happens in exactly the same way.
This is important because over time things will change. Often existing developers will leave a project and new developers will pick up the codebase. By having a single method for instantiating the class through a factory, you ensure that your code is consistent and resilient to changes over time.
One of the post common scenarios where you see the Factory Method Design Pattern is when you have many different interchangeable “drivers”.
Most modern frameworks will allow you to swap what kind of database connection you are using at run time. For example, Laravel 4 uses a Factory class to manage the creation of database connections.
protected function createConnection($driver, PDO $connection, $database, $prefix = "", $config = null)
{
switch ($driver) {
case 'mysql':
return new MySqlConnection($connection, $database, $prefix, $config);
case 'pgsql':
return new PostgresConnection($connection, $database, $prefix, $config);
case 'sqlite':
return new SQLiteConnection($connection, $database, $prefix, $config);
case 'sqlsrv':
return new SqlServerConnection($connection, $database, $prefix, $config);
}
throw new \InvalidArgumentException("Unsupported driver [$driver]");
}
As you can see in the createConnection
method. The type of database connection is passed as an argument and the method tries to create a new instance of that particular database’s associated connection class.
Another good example of the Factory method in practice is the Omnipay payment processing library which allows you to use many different payment gateways using the same consistent API.
When you want to use a particular gateway, you simply pass it as an argument to the Factory:
$gateway = GatewayFactory::create("Stripe");
The Factory Method Design Pattern is an excellent solution to the common problem of requiring many different interchangeable solutions for a given problem. If you find yourself requiring many different implementations, it’s often beneficial to use a Factory
.
Using a Factory hides the implementation details of your code and provides a clean and consistent way to interact with the various pluggable “drivers”.