Design Patterns in PHP [Factory Method Pattern]

Coding (Php 7.x)


Design patterns help solve problem that you do not know you will have, the Factory Method Pattern will make the creation of you object scalable and easy to manage
 
/img/blog/php-design-patterns-factory-method-pattern.jpg

Introduction

 

The factory method pattern establishes a contract for creating an object, but let subclasses define which class to instantiate and what you want to pass to the class that you are instantiating.

This pattern let class defer instantiation to subclasses.

 

The sentence you just read was a high-level definition of the factory method pattern.

 

In this post, you will find out what this sentence actually means and how to implement the factory method pattern into your scripts.

 

Let’s start!

 

Among all the programming paradigm available one of the most used, if not the most common is Object-oriented programming (also called OOP),

 

OOP helps developing reliable and scalable application but sometimes can be complex and not so easy to implement.

 

One of the weak point and more discussed among web developers about OOP is the way it creates objects.

 

The reason is that as a developer we can use several techniques to instantiate objects and some of them are, let’s say, not considered “best practices”.

 

A web developer should aim to use polymorphism and the principle of coding to an interface, not an implementation.

 

A way to do so is to use the Factory Method Pattern.

 

 

Factory Method Pattern

 

Intro to the factory patterns

In the following paragraph, you will see several tutorials regarding this pattern, if you want to learn more have a look at the book "Elements of Reusable Object-Oriented Software" by the Gang of Four.

 

If you had already looked up at factory usually you would have found that there are different types come up.

 

In fact, there are three different factory patterns.

 

The first and simplest one is the “simple factory”, 

 

There is a bit of controversy here,

in fact, software engineers state that this is not an actual pattern.

 

If you consider that a design pattern is a solution to an occurring problem you will soon discover that the simple factory does not solve the problem of scalability.

 

The second version of the factory is the factory method patterns.

It is the version we are going to look in this post,

 

Once understood the idea behind it, 

it’s very simple to implement in your code and you will not only solve the problem of scalability but you will make several aspects of the creation of the object in your scripts way more easy-to-use.

 

This is considered to be a proper design pattern because it achieves the Dependency Inversion principle which is the D of S.O.L.I.D. principles.

 

Lastly, we have the abstract factory pattern.

 

This can be seen as the evolution and a bit more complex factory method, it helps solve the problem that does not find the solution of using the previous and help scale your class even more.

 

I want to deconstruct and analyze the definition we started with:

 

  • The factory method pattern establishes a contract ..., in here a contract can be either an interface or a superclass class;
  • … for creating an object ... this is the end goal, factories pattern are creational patterns, you are going to use the factory method when you need to create an object, and you need to do so in certain ways;
  • … but let subclasses define which class to instantiate ... this is all about polymorphism, in a complex application you are going to have several types of classes that belong to the same category, using factory you can easily instantiate the type you need;
  • … and what you want to pass to the class that you are instantiating. … here is another key point, each object you are instantiating can and probably will have different characteristics, using the factory method pattern creating them will be effortless;
  • This pattern let class defer instantiation to subclasses. The reason you will use this pattern is that you do not know which object you need in advance and what features the object will have, the solution is to put the ConcreteCreator class in charge of the actual creation;

 

 

The problem we are trying to solve

As you know design patterns exist to make solve recurring problems in your web applications.

 

If this is the first time you heard about them, reading this post before continuing will be a good idea.

 

 

 

A recurring problem in OOP is to implement and maintain a system that can create objects.

 

The size of this problem increase when the objects that must be created are of different type and they need to be created at runtime.

 

Why the concept of factory exists?

 

Let’s say we are building an application, 

 

it will be a system that builds cars and checks how cars need to be built in a manufacturing plant.

 

To do so we are doing our due diligence and during the planning phase, we are designing the database and UML schemas.

 

Our application has several classes, a lot of nice features and a nice layout.

 

The problem comes when we actually need to instantiate the object of the classes that we have implemented (the actual model of the car).

 

Imagine we have a different type of classes that need to be instantiated at different timesform different part of your code, and each of them can have different characteristics.

 

The question is: how do we instantiate this class correctly?

 

For example we may have different models of our car:

 

 

 

The solution, in this case, is to delegate the creation of the object to a factory that will be in charge of creating the object of the specific class you need.

 

 

 

Why do we need a factory pattern?

Continuing the tutorial of the previous paragraph, probably the type or model of car that will be built is going to have a specific order or maybe instead they are built randomly.

 

Either way, we should not write this business logic in several places in our application but have this logic (and all the parameters that follow) in only a class, then use that class to create all the objects we need.

 

Here are some class that we may need.

 

 

 

 

What are the pros in that?

Using this factory class we can now call this class and the method createCar() inside from different places within our application instead of writing the same logic over and over,

 

Also, if we need to update the algorithm we can do so from only one place.

 

Another big advantage of this process is that, after we decided that we are going to use the random method, thus use the RandomCarFactory the createCar() will create a model without us specify anything.

 

We can just call different types of class at runtime enhancing the scalability by using polymorphism.

 

 

When to use this pattern?

In the example above two main reasons stand out, 

 

The factory pattern in this case act as a caller (an "invoker" in you will), we have a factory that needs to create several cars. 

 

The factory may need to know some details about the car, but it is not its main concern.

 

When we have to build a new car, we can simply invoke the class responsible and tell what type of car we require.

 

Note that to build a car we also need to know a lot of characteristics.

 

Colour, the engine, the number of seats, also you might need the address of the owner to which deliver the car, and the legal requirement in the country the car as been bought.

 

The pattern instead does not need to know any of it, the factory pattern only handles the creation.

 

Using the factory method pattern help we create a new object on demand without having to know all the details or whether there are dependencies during this process.

 

 

How to implement the solution

Throughout this tutorial, I have used a really simple example of a car factory and the different model that can be built.

 

In this part, we are going to write a more complicated feature using a different and more specific example.

 

In this tutorial, we are building a videogame based on the sport of football, a managerial type of videogame.

 

In a football pitch, there are several players and they have different roles.

 

We’ll use the role Goalkeeper, Defender, Midfielder, and Forward.

 

You guessed it,

 

those are also the class that we need to create in our application.

 

The UML looks like this so far

 

 

 

 


 

/**
 * The Player interface declares the operations that all players must implement.
 */

interface Player
{
  public function action(): string;
}

/**
 * Each role provide various implementations of the Player interface.
 */

class Goalkeeper implements Player
{
  public function action(): string
  {
    return "I block the shot";
  }
}

class Defender implements Player
{
  public function action(): string
  {
    return "I stop the striker";
  }
}

class Midfielder implements Player
{
  public function action(): string
  {
    return "I pass the ball";
  }
}

class Forward implements Player
{
  public function action(): string
  {
    return "I kick the ball";
  }
}

If this code seems complicated you may want to start with the basics of PHP.

 

We now have all the class necessaries to use our application, the problem we haven’t solved yet is that the users need to form a squad.

 

We forecast that in this videogame there will be users that prefer an attacking way to play the game whereas others would prefer a more defensive approach.

 

This means that we do not know what type and how many time they are going to create the player (objects of these classes).

 

Look like is time for the Factory method pattern:

 

 

 


 

/**
 * This class indicates the factory method that is assumed to return an object of a Player class.
 * The PlayerFactory's subclasses usually administer the implementation of this method.
 */

abstract class PlayerFactory
{
  /**
  * Note that the PlayerFactory provides some default implementation of the * factory method.
  */
  abstract public function spawnPlayer(): Player;
}

/**
 * PlayerFactorys' classes override the factory method to change the resulting product's type.
 */

class GoalkeeperFactory extends PlayerFactory
{
  public function spawnPlayer(): Player
  {
    return new GoalKeeper;
  }
}

class DefenderFactory extends PlayerFactory
{
  public function spawnPlayer(): Player
  {
    return new Defender;
  }
}

class MidfielderFactory extends PlayerFactory
{
  public function spawnPlayer(): Player
  {
    return new Midfielder;
  }
}

class ForwardFactory extends PlayerFactory
{
  public function spawnPlayer(): Player
  {
    return new Forward;
  }
}

/*
 Creating a player of type goalkeeper on runtime
*/

$goalkeeperFactory = new GoalkeeperFactory()
$goalkeeper = $goalkeeperFactory->spawnPlayer();
echo $goalkeeper->action();
// "I stop the striker"



 

Note that all the code necessary to create the new goalkeeper in our script is not aware of any task (of methods) the goalkeeper should perform.

 

We do not care about his age, height, skill level at this point. 

 

 

The end result

 

 

The example we have just seen in here has a lot of classes yet it is very straightforward.

 

This is a practical example of how you would apply the factory method pattern in your application.

 

This pattern aims to solve a specific problem for a specific use case and it is also considered one of the most commonly used creational design pattern since the gang of four published their book more than 2 decades ago.

 

 

Conclusion

 

Learning how to correctly use design patterns, in general, is a very important skill for anyone that feels ready to skill up his coding performance and have a deep understanding of architect the code in a web application.

 

There are several resources such a GitHub repository that can be used to learn them:

 

 

Also, have a read at Design Patterns: Elements of Reusable Object-Oriented Software written by Erich Gamma, John Vlissides, Richard Helm, Ralph Johnson (Commonly name Gang of Four).

 

Where to go from now?

 

If you enjoyed this creational pattern now it is time to see some structural one, here is the Decorator design pattern

 

Also,

 

all the method described in this post work way faster in an up to date version of PHP so you can check the guide to PHP 7.4 out.

 

 
 
If you like this content and you are hungry for some more join the Facebook's community in which we share info and news just like this one!

Other posts that might interest you

Coding (Php 7.x) Dec 2, 2019

PHP 7.4 (Changes & Performance)

See details
Coding (Php 7.x) Dec 12, 2019

Decorator in PHP [Design pattern with examples]

See details
Coding (Php 7.x) Dec 21, 2019

Observer in PHP [Design pattern with examples]

See details
Get my free books' review to improve your skill now!
I don't want to improve