Early previewThis guide is in development. Items tagged verify are still being checked against official docs.
nebx Learn
GitHub
Menu
Home/PHP/Design patterns/Factory Method
PHP

PHP

Pragmatic server-side language that powers a large share of the web.

Paradigm
OOP, procedural, functional features
Typing
Dynamic with gradual typing (strict_types)
Memory
Reference counting + cycle collector
Runs
Zend Engine, bytecode + OPcache, optional JIT
Concurrency
Shared-nothing per request; Fibers (8.1)
Creational pattern

Factory Method

Intent

Defines an interface for creating an object but lets subclasses decide which class to instantiate.

Problem

Your logistics app only knows trucks. Adding ships means touching every place that calls new Truck().

Solution

Replace direct construction with a call to a factory method that subclasses override. Client code works with the product interface only.

Real-world analogy

Think of it like this

A logistics company decides whether a shipment travels by truck or by ship. The customer only asks for delivery.

Structure

association / extends implements / depends on
Creator + someOperation()+ createProduct(): Product 3 ConcreteCreatorA + createProduct(): Product 4 «interface» Product + doStuff() 1 ConcreteProductA 2 ConcreteProductB

Hover or tap a numbered role to highlight it in the diagram.

  1. 1Product — Product declares the interface common to everything the creator and its subclasses can produce.
  2. 2ConcreteProductA — Concrete Products are the different implementations of that interface.
  3. 3Creator — Creator declares the factory method that returns a Product. Its main job is still business logic that uses the product.
  4. 4ConcreteCreatorA — Concrete Creators override the factory method to return a different product type.

Try it

InteractiveAsk each creator for a plan. Then add a new creator without touching existing code.
Creators
createTransport()
Product appears here
logistics.plan()
// pick a creator

Code example

factory.php
interface Transport { public function deliver(): string; }
final class Truck implements Transport { public function deliver(): string { return 'by road'; } }
final class Ship implements Transport { public function deliver(): string { return 'by sea'; } }

abstract class Logistics
{
    abstract protected function createTransport(): Transport;   // factory method

    public function plan(): string
    {
        return $this->createTransport()->deliver();
    }
}

final class RoadLogistics extends Logistics
{
    protected function createTransport(): Transport { return new Truck(); }
}

Applicability

Use Factory Method when you don't know in advance the exact types your code will work with.

Use Factory Method when you want users of your library to extend its internal components.

Use Factory Method when you want to reuse existing objects instead of rebuilding them.

How to implement

  1. Make all products follow a common interface
  2. Add an empty factory method to the creator, returning the product interface
  3. Replace constructor calls in the creator with calls to the factory method
  4. Create a creator subclass for each product type and override the factory method

Pros and cons

Pros

  • Avoids tight coupling between creator and concrete products
  • Single Responsibility: creation code in one place
  • Open–Closed: new products without breaking clients

Cons

  • Can add many subclasses

Relations with other patterns

Check yourself

Check yourself

A document editor opens .docx, .pdf and .md files, and plugin authors must add new formats by subclassing.

Saved in this browser only. Part of Creational patterns (0/5), Hands-on: patterns with live demos (0/5).