PHP Factory Design Pattern: Learn Using Code Examples in 2023

Last Updated on

CraftyTechie is reader-supported. When you buy through links on our site, we may earn an affiliate commission.

What is the Factory Pattern in PHP

The Factory pattern in PHP will make sense only if you understand the factory design pattern in general. Here’s a glimpse of the final design diagram from the article.

Factory Pattern in PHP
BookACar Application Design Diagram

We will build this design incrementally and will implement it in PHP. Join us in this exciting journey of developing a car booking application using factory pattern in PHP.

What is the Factory Pattern

The Factory design pattern is one of the “creation” types. It defines a method for object creation in a superclass and then delegates the instantiation into sub-classes. This pattern makes it easy to switch out implementations while keeping similar functionalities.

Factory Design Pattern
Factory Design Pattern

The objective of this pattern is to encapsulate the object creation logic in a module and separate it from the core business logic.

Sounds abstract? Don’t worry, as this article will not only help you understand the factory pattern in PHP really well but also open up ways for you to develop more design-oriented flexible software systems.

BookACar Application | A Real World Example of Factory Pattern in PHP

BookACar | The First Release

So, you have been a lead developer in one of the thriving startups, BookACar. It helps customers to book and purchase a car of their favorite type and brand. The application has yet to become popular, so at the moment, it’s a collaboration with one brand. 

You’re tempted to come up with an MVP as soon as possible, and guess what? Your team may end up releasing the application with code like this.

Factory Pattern in PHP
BookACar Application First Version

But there is more than one type of Car…

Oops! Guess what? Some requirements still need to be included. There is more than one type of car. 

Types of Cars
Types of Cars

But the code above doesn’t deal with this. So, time for another iteration. This time developers refactor it like this.

Factory Pattern in PHP
Refactored Code

Technically, nothing is wrong with this implementation. But, from a design POV, there are better ways to handle it.

So, What’s Wrong with this Implementation?

The implementation above violates two fundamental design principles.

Single Responsibility Pattern 

Single Responsibility Pattern says a module should have one and only one job. The implementation above delegates objects initialization to the orderCar() module. Ideally, this module should focus on booking a car rather than initializing cars.

Single Responsibility Principle
Single Responsibility Principle

Open-Closed Principle

The open-Closed Principle says that modules should be open to extension but closed for modification.

The implementation above initializes concrete objects of a more abstract Car type.

Factory Pattern in PHP
Concrete Car Classes

Coding like this would end up in a maintenance nightmare when there are changes such that you need to add or remove concrete classes. You have no option but to modify the existing modules to make those changes. 

Let’s say that the car brand discontinues minivans and introduces hatchback cars.

Factory Pattern in PHP
Updated Car CATA

How will you accommodate this change? At the moment, there’s one way, and that’s how it is.

Open-Closed Principle
Violate Open-Closed Principle

See how a few changes messed up the existing code. Imagine if you have been using the same initialization code in 10 other application modules. Sounds horrible, right?

Encapsulate the Change

Change is inevitable in software development. You can’t escape it, but you can certainly encapsulate it. 

But what do we mean by encapsulating the change? Putting it in simpler terms, it aggregates your applications’ frequently changing aspects into a separate module. 

How is that helpful? So, when you encapsulate the change, you contain it in one place, and it doesn’t ripple out to the rest of your application, as seen above. You can deal with the change in one place, and your application would be able to adapt to it.

And that’s the core idea of a flexible and maintainable software design. You tame the changes, and it doesn’t hurt your application.

Factory Pattern in PHP
Introducing Car Factory Class

The Class that Makes Factory Pattern in PHP Work

We have a new class to encapsulate the changes, and we will call it CarFactory.

Car Factory Class
Car Factory Class

BookACar | The Second Release

So, developers will have to refactor BookACar class to integrate it with the CarFactory.

Factory Pattern in PHP
BookACar v2

Now, the object initialization happens in the factory class method and orderCar() delegates initialization to it which was previously tied to the orderClass() itself.

Now, if we had to add a new car or remove an older one, we know the factory class is the go-to for that purpose. The rest of the application will remain largely unaffected by that change.

We’re Not Done Yet to use the Factory Pattern in PHP

So, that’s out-of-the-box thinking and opens up new ways to think about application development. However, it is just a programming paradigm, not the factory pattern itself. The concepts we have been through will solidify the ground for the factory pattern in PHP we are about to see.

Meanwhile, here is a bigger picture of the application design thus far.

SimpleFactory Class
SimpleFactory Class

The Factory Pattern in PHP Example Complete

BookACar is now Popular!

BookACar has been the talk of the town and collaborates with an electric vehicle EV brand.

Now, the application has two menus – one for EVs and another for the existing brand.

Team A is working on the EV booking functionality of the application, and Team B is working on the existing application. You’re the lead architect now – Congratulations! But the game is not over yet!

How about the EVs? They are different from the existing brand of cars. We don’t want to place them all in one factory class. 

What if we add a new factory class for EVs?

Factory Pattern in PHP
Two Factory Classes

Well, that undoubtedly is one of the right approaches, but there’s a business requirement that we need to standardize for every car. Let’s zoom in on that next.

BookACar Purchase Policy

BookACar has the same procedure for ordering a car regardless of the type and brand. We want to keep that standard and not let any part of the application override that. The design above uses more than one factory, but the orderCar() is a standard method for both cars. 

We want to ensure that every Team in the present or future uses the same orderCar() method. In other words, we want to tie up the car creation and order in the BookACar class. 

But that would undo all the effort? Well, we will keep the creation logic in a Factory Method. The orderCar() will call this method. The orderCar() would not be concerned with the type of car, just as it was when we stripped out the creation logic last time. In more technical terms, these two methods will be decoupled.

So how to go about this problem?

BookACar Class with Abstract Factory Method

With the objective in mind, let’s modify the BookACar class. 

Abstract Factory Method
Abstract Factory Method

The Factory Method

Factory Pattern in PHP
Abstract Factory Method

An abstract method expects sub-classes to implement it the way they want to. The orderCar() is a concrete method. In our case, the two sub-classes of BookACar will implement createCar() in their way. The orderCar() will remain the same for all the sub-classes.

The Bigger Picture of the Factory Pattern in PHP

Concrete Factory Methods
Concrete Factory Methods

What’s the benefit? See, the sub-class decides the brand of the car, but the orderCar() is not concerned with what sub-class we have. It sees them all as Cars. Both methods are loosely coupled, and the design remains flexible.

Let’s Order A Car…

1. First: Let’s choose the EV brand.

Factory Pattern in PHP
Initialize Concrete Creator Class

2. Order an EV SUV.

orderCar
orderCar()

3. The orderCar() calls createCar() as follows.

Factory Pattern in PHP
createCar

4. Finally, the orderCar() performs the standard booking procedure.

returnCar
returnCar

Factory Pattern in PHP | BookACar Architecture Design Pattern

Here’s a complete picture of what we have designed thus far, and that’s what the factory design pattern is.

BookACar Design Diagram

Factory Method Design Pattern in PHP

The following code recreates the factory method design pattern in PHP for the BookACar application.

Code | Factory Method Design Pattern in PHP

<?php
class Car {
 
    private $name;
 
    function setName($name) {
        $this->name = $name;
    }
 
    function getName() {
        return $this->name;
    }
 
    function order() {
        $name = $this->getName();
        echo "Order for ${name} has been placed".PHP_EOL;
    }
 
    function purchase() {
        $name = $this->getName();
        echo "Purchase for ${name} has been made".PHP_EOL;
    }
 
    function ship() {
        $name = $this->getName();
        echo "${name} has been shipped".PHP_EOL;
    }
}
 
class HatchBack extends Car {
    function __construct() {
        $this->setName("HatchBack");
    }
}
 
class Sedan extends Car {
    function __construct() {
        $this->setName("Sedan");
    }
}
 
class SUV extends Car {
    function __construct() {
        $this->setName("SUV");
    }
}
 
class EVSUV extends Car {
    function __construct() {
        $this->setName("EVSUV");
    }
}
 
class EVSedan extends Car {
    function __construct() {
        $this->setName("EVSedan");
    }
}
 
abstract class BookACar {
 
    abstract public function createCar($type): Car;
 
    function orderCar($type) {
 
        $car = $this->createCar($type);
 
        $car->order();
        $car->purchase();
        $car->ship();
 
        return $car;
    }
 
}
 
class BookEV extends BookACar {
 
    public function createCar($type): Car {
       
        $car = null;
 
        if($type == "evsuv") {
           $car = new EVSUV();
        }
        else if($type = "evsedan") {
            $car = new EVSedan();
        }
 
        return $car;
    }
}
 
class BookNormal extends BookACar {
 
    public function createCar($type): Car {
       
        $car = null;
 
        if($type == "hatchback") {
           $car = new HatchBack();
        }
        else if($type = "sedan") {
            $car = new Sedan();
        }
        else if($type == "suv") {
            $car = new SUV();
        }
 
        return $car;
    }
}
 
 
function main() {
    $bookEV = new BookEV();
 
    $evSUV = $bookEV->orderCar("evsuv"); //Let's order an EV SUV.
 
    echo "I have bought an ".$evSUV->getName().PHP_EOL;
}
 
main();
?>

Factory Pattern in PHP : Finished Design Pattern

Order for EVSUV has been placed
Purchase for EVSUV has been made
EVSUV has been shipped
I have bought an EVSUV

Pros and Cons of the Factory Pattern in PHP

ProsCons
Loose Coupling between Creator and Product.You need to write a lot of boilerplate code and sub-classes to implement the pattern.
Flexible and maintainable design Can be difficult to comprehend sometimes.
Satisfies Single Responsibility Principle
Satisfies Open-Closed Principle

Where is Factory Pattern Used?

  • When new kinds and types of object variations are added to your application. The pattern keeps the creation code separate from the business logic. So it is flexible when you want to add more objects and their associated creator classes.
  • When you want to implement a UI framework or library. This framework adds more visual elements per the changing UI trends. So, using this pattern will allow extension without impacting the entire application.
  • You can use it for memory optimization by keeping a pool of memory-intensive objects. 

Frequently Asked Questions?

Is Factory a Static Method?

Some implementations use static factory methods, which closes the door for class inheritance. You can use a static factory method when you have one factory class with no sub-classes. For instance – the CarFactrory in the examples above can use a static createCar() method.

Is Factory a Singleton Method?

No, you can create as many objects as you need with the factory method. However, you can limit the object creation by creating a pool that’s not a part of the factory method. The Singleton pattern is a different pattern. It creates one global instance or a pool of instances for the entire application and focuses on memory optimization.

What is the Factory Pattern in PHP?

The factory design pattern is not a programming language-specific tool but a general idea about encapsulating object creation in a scenario where you can have variance in objects.

Is Factory a Function or Class?

The implementation of a factory can vary. You can implement a Factory class, but sometimes you need to loosely couple creation and business logic, and that’s where you can use abstract factory methods, just as we did above.

Using the Factory Pattern in PHP today

Phew! We covered a lot of ground covering a whole lot about factory patterns in PHP. As a quick summary, we have learned that the goal of the factory pattern is to encapsulate the object creation code from the core logic. It defines a bunch of sub-classes from a more generic class and delegates the task of object instantiation to these sub-classes.

The article uses a real-world example the factory pattern in PHP. It’s an application for booking and purchasing cars. The application collaborates with brands that offer different types of cars. The component of the application that varies is the type and brand of car – as more and more brands sign up. This scenario was ideal for implementing a factory pattern.

We have started from the bottom up from a simple and tightly coupled application code to a more flexible factory design pattern. The article also includes the complete application code for this application in PHP.

Hope you have been able to take away some value. Stay tuned for more at FuelingPHP.

Books on Design Patterns

Want to learn more about Design Patterns? There are many great resources online. We recommend the following books for your collection as they both can teach you the theoretical and the application of using design patterns in your day-to-day programming. Feel free to use the following Amazon affiliate links if you’d like to purchase them and a way to support our efforts.

Design Patterns: Elements of Reusable Object-Oriented Software

Design Patterns: Elements of Reusable Object-Oriented Software book

This is the book that started it all. I believe that every programmer should have a referenced copy to this book at some point in their career. There have been many updates and excellent newer content through the years, but this is a classic. It still stands the test of time and is just as relevant for today as it was in the original printing in the 90s.

Check it out on amazon

Learning PHP Design Patterns

This is an excellent book to go beyond the theory and apply it to writing good PHP code. Learning PHP Design Patterns is published by the popular O’Reilly media company. O’Reilly consistently publishes some of the most useful reference material related to software development. They are known to provide materials that thoroughly cover a topic in a way that is simple to understand. I recommend this book to every PHP developer.

Check it out on amazon

Want to see our full review of books on design patterns? Read our huge review article on over 15 design pattern books.

Design Patterns in PHP Learning Series.

This article is part of our series of design patterns in PHP. We are going through all of the patterns and showing how they can help you build better applications. Browse through our full list of patterns below.

Did you find this article helpful?

Join the best weekly newsletter where I deliver content on building better web applications. I curate the best tips, strategies, news & resources to help you develop highly-scalable and results-driven applications.

Build Better Web Apps

I hope you're enjoying this article.

Get the best content on building better web apps delivered to you.