Skip to main content
Design Patterns – Complete Beginner to Advanced Guide
CHAPTER 07 Intermediate

Factory Method Pattern

Updated: May 16, 2026
30 min read

# CHAPTER 7

Factory Method Pattern

1. Introduction

Imagine you are building a logistics application. Initially, it only handles truck deliveries, so your code is filled with new Truck(). A year later, your company becomes massively successful and adds sea deliveries. Now, you have to dig through your entire codebase, find every new Truck(), and wrap it in an if/else statement to handle new Ship(). This is fragile, tightly coupled code that violates the Open/Closed Principle. The Factory Method Pattern solves this. It provides a dedicated interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. In this chapter, we will master the Factory Method, learning how to centralize the new keyword and build infinitely extensible creation architectures.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define the core intent of the Factory Method Pattern.
  • Encapsulate the new keyword into dedicated creator classes.
  • Understand the relationship between the "Creator" and the "Product" interfaces.
  • Apply the Factory Method to adhere to the Open/Closed Principle (OCP).
  • Refactor tightly coupled instantiation logic into dynamic factories.

3. The Core Concept

The Factory Method suggests that you replace direct object construction calls (using the new operator) with calls to a special *factory method*.
  • The Decoupling: The objects returned by a factory method are often referred to as *products*. Your business logic only interacts with the *Product Interface*, not the concrete classes.
  • The Strategy: You create an abstract Logistics class with a createTransport() factory method. The RoadLogistics subclass implements the method to return a Truck. The SeaLogistics subclass implements it to return a Ship.

4. Creators and Products

The pattern relies on two parallel inheritance hierarchies.
  1. 1. The Products: The interface (Transport) and the concrete objects (Truck, Ship) that do the actual work.
  1. 2. The Creators: The abstract class (Logistics) that declares the factory method, and the concrete factories (RoadLogistics, SeaLogistics) that execute the new keyword.

5. Why is this better?

  • Single Responsibility (SRP): The code that decides *how* to create a complex Truck is moved out of the business logic and isolated inside the factory.
  • Open/Closed Principle (OCP): If you need to add Air Deliveries, you DO NOT touch the existing code. You simply create a new Plane product and a new AirLogistics creator. The system is infinitely extensible.

6. UML Diagram

*Factory Method Structure*
text
12345678
[ Creator ] <------------------------- [ Product ]
+ createProduct(): Product             + doStuff()
       ^                                     ^
       | (Inherits)                          | (Implements)
------------------                   -----------------
|                |                   |               |
[ ConcreteCreatorA ]               [ ConcreteProductA ]
+ createProduct() { return new A }   + doStuff()

7. Code Example (PHP)

Let's implement the Logistics example.
php
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
<?php
// --- 1. The Product Interface ---
interface Transport {
    public function deliver();
}

// --- 2. Concrete Products ---
class Truck implements Transport {
    public function deliver() {
        echo "Delivering cargo by land in a box.\n";
    }
}

class Ship implements Transport {
    public function deliver() {
        echo "Delivering cargo by sea in a container.\n";
    }
}

// --- 3. The Creator (Abstract Factory Class) ---
abstract class Logistics {
    // The Factory Method
    abstract public function createTransport(): Transport;

    // Core business logic that relies on the factory
    public function planDelivery() {
        // Call the factory method to create a Product object.
        $transport = $this->createTransport();
        // Now use the product.
        $transport->deliver();
    }
}

// --- 4. Concrete Creators ---
class RoadLogistics extends Logistics {
    public function createTransport(): Transport {
        return new Truck();
    }
}

class SeaLogistics extends Logistics {
    public function createTransport(): Transport {
        return new Ship();
    }
}

// --- 5. Client Code ---
// The client chooses the factory, but the factory handles the object creation.
function clientCode(Logistics $logistics) {
    $logistics->planDelivery();
}

echo "App: Launching Road Logistics.\n";
clientCode(new RoadLogistics()); // Output: Delivering cargo by land in a box.

echo "\nApp: Launching Sea Logistics.\n";
clientCode(new SeaLogistics());  // Output: Delivering cargo by sea in a container.
?>

8. Best Practices

  • Parameterized Factories (Simple Factory): Sometimes, creating a full inheritance hierarchy of Creators is overkill. A common variant is the "Simple Factory" (technically not the GoF Factory Method, but widely used). This is a single class with a method like createVehicle($type) containing a switch statement that returns new Truck() or new Ship(). Use this for simpler logic.

9. Common Mistakes

  • The Empty Creator: If your Logistics base class *only* contains the factory method and has zero other business logic (like planDelivery()), you don't really need the Factory Method pattern. You are likely over-engineering. The true power of the Factory Method is when the base class has complex, shared business logic that relies on an object that its subclasses must define.

10. Mini Project: Build a Notification Factory

  1. 1. Products: Create a Notification interface with a send($msg) method. Create EmailNotification and SMSNotification classes.
  1. 2. Creators: Create a simple NotificationFactory class.
  1. 3. Logic: Create a static method create($type). If $type == 'email', return a new Email object.
  1. 4. Action: From your main script, generate both an Email and an SMS using the factory, and call send(). Notice how the new keyword never appears in your main script.

11. Practice Exercises

  1. 1. Explain how the Factory Method Pattern specifically enforces the Open/Closed Principle (OCP) when adding a new type of product to the system.
  1. 2. Describe the difference between the "Creator" classes and the "Product" classes in the Factory Method UML architecture.

12. MCQs with Answers

Question 1

In the Factory Method pattern, the client code (business logic) interacts with the newly created objects exclusively through:

Question 2

What is the primary architectural benefit of moving the new keyword out of your main business logic and into a dedicated Factory class?

13. Interview Questions

  • Q: Explain the difference between the formal Gang of Four "Factory Method Pattern" and the common idiom known as a "Simple Factory" (a single class with a massive switch statement).
  • Q: In a massive enterprise application, walk me through a scenario where hardcoding the new keyword for database models deep within your controllers would create a testing nightmare. How does the Factory pattern resolve this?
  • Q: Look at this code containing a complex if/else block creating 5 different types of enemy characters in a video game. Refactor it on the whiteboard using the Factory Method pattern.

14. FAQs

Q: Can a Factory return an existing object instead of creating a new one? A: Yes! That is a massive advantage of using a Factory. You can combine a Factory with a Cache (or a Singleton). When createProduct() is called, the Factory can check if the object is already in memory. If so, return it; if not, use new. The client code never knows the difference.

15. Summary

In Chapter 7, we engineered a dynamic assembly line. We recognized that hardcoding instantiation with the new keyword creates brittle, tightly coupled architecture that breaks the Open/Closed Principle. By deploying the Factory Method Pattern, we successfully isolated the complex logic of object creation into dedicated Creator classes. Our business logic now floats cleanly above the implementation details, interacting purely with Product Interfaces. This pattern allows us to infinitely extend our systems with new object types without ever rewriting existing code.

16. Next Chapter Recommendation

The Factory Method creates one specific product. But what if we need to create an entire matching *family* of products? Proceed to Chapter 8: Abstract Factory Pattern.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·