Factory Method Design Pattern with Example in PHP
Factory Method is one of the creational design pattern. In simple words, we can say: factory method is a creational design pattern that is mainly focused on object creation in an abstract way from sub-classes. It means we will let the sub-class to create object of product concrete class.
When to use Factory Method design pattern
When we don’t know how many types of product or sub classes could be needed.
Make things loosely coupled
When we need to create object from sub-classes instead of product concrete class
Advantage of Factory Method design pattern
The Factory method design pattern makes the code loosely coupled & reuse able. This way we can follow the single responsibility and open, close principle of SOLID. Besides, we don’t need to worry about the enhancement or scalability of services.
Real Life Example in PHP
Let’s take an example of book library, suppose we run a small book library and for now we are selling Programming Books. Within a few months we got popularity and getting many request for storing Mathematic Books. In future we may have much more requests for more genres. That is really good for the business.
So here we don’t know beforehand what we may need in future. So if we write code only taking care of programming related books selling logics then we may encounter to refactor code again. Even we may need to write entire logics again for other genres. That is really bad 🙁
So let’s jump into the code and see how can solve above discussed problem:
First we will create an abstract class that will contain a factory method like below:
abstract class BookFactory
{
abstract public function createBook($type): GenericBook;
}
This class is basically called Factory Class. Since it’s containing an abstract method so the class that will be derived from it will must implement this method & follow the signature. It means the return type of createBook method will be an interface of GenericBook.
Now let’s create a sub-class that is basically Factory Concrete Class. The class which is responsible for creating object of Product Concrete class.
class Book extends BookFactory
{
protected $name, $author;
public function __construct($name, $author)
{
$this->name = $name;
$this->author = $author;
}
public function createBook($type): GenericBook
{
try {
return new $type($this->name, $this->author);
} catch (\Throwable $th) {
throw $th;
}
}
}
So all is going good, we have implemented createBook method with proper signature & this is a constructor method for setting up basic things. We are creating object here on fly on the run time, beforehand we don’t know that object we really want to create but as long as it’s returning GenericBook interface all is good. Through the interface we can enforce the Product Concrete Class to implement required methods.
Let’s create the interface:
interface GenericBook
{
public function bookName(): string;
public function bookAuthor(): string;
public function price();
}
Now let’s create Product Concrete Class that contains logics about particular genre books.
class ProgrammingBook implements GenericBook
{
private $bookName, $bookAuthor;
private $price = '$120';
public function __construct($name, $author)
{
$this->bookName = $name;
$this->bookAuthor = $author;
}
public function __get($name)
{
echo $name . ' prop is not available, try method';
}
public function bookName(): string
{
return $this->bookName;
}
public function bookAuthor(): string
{
return $this->bookAuthor;
}
public function price()
{
return $this->price;
}
}
Now our code is entirely following Factory Method Design Pattern and is loosely coupled. Below way client will use the class:
$book = new Book('PHP Book', 'Rasmus Lerdorf');
$programmingBook = $book->createBook('ProgrammingBook');
echo $programmingBook->bookName() . '<br>';
echo $programmingBook->bookAuthor() . '<br>';
echo $programmingBook->price() . '<br>';
This way client may create as many programming book as they need.
Now If we need more genre books then simple we can create another class and implement all logics to that particular class and don’t need to touch anything else. Even we can take advantage of common things that already have on the ProgrammingBook class.
Here is how to achieve it:
class MathBook extends ProgrammingBook
{
private $price = '$90';
public function price()
{
return $this->price;
}
}
Supposed we need to sell Math books & we have all things same as programming book but price is different, so we can simple create a class for MathBook and extends ProgrammingBook. Since price is different we can override from particular class, that is really cool 😀
That’s all for the Factory Method, don’t forget to comment your recommendation/suggestion.
I am professional Web Designer & Developer. I have 5+ years of experience in relevant field. Currently I am working for a private software company named “Ollyo” as a Senior Staff Software Engineer.