Design Pattern: Factory Pattern in PHP

Factory pattern helps to separate the creator of the objects from the object classes. The creator/factory is responsible for generating objects.

Factory implementation process is not strict or predefined. The implementation depends on how we identify and generate different objects.

NOTES

In this article, we discuss the implementation of the Factory Pattern in PHP.

See the Factory in other languages in the “Other Code Implementations” section. Or, use the link below to check the details of the Factory Pattern-

Implementation

Use the following steps to implement the Factory pattern in PHP-

  • Create item interface. This interface will be the base interface for all the item/product classes.
  • Create item/product classes and implement the interface.
  • Create factory class.
  • In factory class create a method to generate item/product classes. Accept some parameter to identify which object we want to generate, this identifier can be a string, integer, or any other type according to the preference.
  • Based on the provided identifier generate a new object of the desired class and return that object.

Here is a simple example of Factory pattern implementation in PHP-

<?php
// Factory pattern implementation on PHP

// Item/Product base interface
interface BaseItem {
    function operation1(): void;
    function operation2(): void;
}

// item class
class Item1 implements BaseItem {
    public function operation1(): void {
        echo "Item 1: operation 1n";
    }

    public function operation2(): void {
        echo "Item 1: operation 2n";
    }
}

// Define another item class
class Item2 implements BaseItem {
    public function operation1(): void {
        echo "Item 2: operation 1n";
    }

    public function operation2(): void {
        echo "Item 2: operation 2n";
    }
}

// Factory
class Factory {

    // Make this method static if you prefer
    public function getItem(int $type): ?BaseItem {
        // Generate object based on the parameter passed
        // If $type is 1 then return Item1
        // If $type is 2 then return Item2
        switch ($type) {
            case 1: return new Item1();
            case 2: return new Item2();
            default: return null;
        }
    }
}


// --- Demo ---
$myFactory = new Factory();

$item1 = $myFactory->getItem(1);
$item1->operation1();
$item1->operation2();

$item2 = $myFactory->getItem(2);
$item2->operation1();
$item2->operation2();

Output of the above code will be as below

Item 1: operation 1
Item 1: operation 2

Item 2: operation 1
Item 2: operation 2

Examples

Let’s take a look at a few examples of Factory pattern implementation in PHP.

Example #1: Transport

Here is an example of a simple Factory pattern implementation.

We are implementing a few item classes which represent different transports, and then we have a factory class for generating objects of those item classes.

Transport Interface

  • Create file “Transport.php”.
  • Define an interface “Transport”.
  • Declare methods as per requirement. Here we have methods – “start”, “stop”, “repair”.
<?php
// Transport.php

namespace BigBoxCodeDesignPatternFactoryTransport;

interface Transport {
    function start();
    function stop();
    function repair();
}

Bike Class [Item Class]

  • Create file “Bike.php”.
  • Create class “Bike”.
  • Implement interface “Transport” for the class.
<?php
// Bike.php

namespace BigBoxCodeDesignPatternFactoryTransport;

class Bike implements Transport {
    public function start() {
        echo "Bike startedn";
    }

    public function stop() {
        echo "Bike Stoppedn";
    }

    public function repair() {
        echo "Bike Repairn";
    }
}

Car Class [Item Class]

  • Create file “Car.php”.
  • Create class “Car” and implement “Transport” interface.
<?php
// Car.php

namespace BigBoxCodeDesignPatternFactoryTransport;

use BigBoxCodeDesignPatternFactoryTransportTransport;

class Car implements Transport {
    public function start() {
        echo "Car startedn";
    }

    public function stop() {
        echo "Car Stoppedn";
    }
    
    public function repair() {
        echo "Car Repairn";
    }
}

Plane Class [Item Class]

  • Create file “Plane.php”.
  • Create class “Plane” and implement “Transport” interface.
<?php
// Plane.php

namespace BigBoxCodeDesignPatternFactoryTransport;

class Plane implements Transport {
    public function start() {
        echo "Plane startedn";
    }

    public function stop() {
        echo "Plane Stoppedn";
    }

    public function repair() {
        echo "Plane Repairn";
    }
}

Transport Factory Class

  • Create factory file named “TransportFactory.php”.
  • Create class “TransportFactory”.
  • Define method named “getTransport” which accepts a string param. and based on the param it generates an object of Bike/Car/Plane. And finally returns the object.

You can make the getTransport function static, if you prefer.

<?php
// TransportFactory.php

namespace BigBoxCodeDesignPatternFactoryTransport;

class TransportFactory {

    public static function getTransport(string $type): ?Transport {
        switch (strtolower($type)) {
            case "bike":
                return new Bike();
            case "car":
                return new Car();
            case "plane":
                return new Plane();
        }

        return null;
    }
}

Demo

To use the implementation, create an object of “TransportFactory” first. Then use the object to generate object for bike/car/plane.

Then we can use the generated bike/car/plane object according to our need.

<?php
// demo.php

require __DIR__ . '/../../vendor/autoload.php';

use BigBoxCodeDesignPatternFactoryTransportTransportFactory;


$transportFactory = new TransportFactory();

$transport1 = $transportFactory->getTransport("bike");
$transport1?->start();

$transport2 = $transportFactory->getTransport("car");
$transport2?->start();

$transport3 = $transportFactory->getTransport("plane");
$transport3->start();

Output

We will get the following output if the above demo code is executed.

Bike started
Car started
Plane started

Example #2: Transport [Factory Method]

Let’s check a different implementation of factory than a simple factory.

We are implementing a factory method for generating transport objects.

Transport Interface

  • Create file “Transport.php”.
  • Define interface named “Transport”.
  • Declare some methods as per requirement.
<?php
// Transport.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

interface Transport {
    function start();
    function stop();
    function repair();
}

Bus Class [Road Transport – Concrete Item Class]

  • Create file “Bus.php”.
  • Create class “Bus” and implement interface “Transport”.
<?php
// Bus.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

class Bus implements Transport {
    public function start() {
        echo "Bus startedn";
    }

    public function stop() {
        echo "Bus Stoppedn";
    }

    public function repair() {
        echo "Bus Repairn";
    }
}

Bike Class [Road Transport – Concrete Item Class]

  • Create file “Bike.php”.
  • Create class “Bike” and implement the “Transport” interface.
<?php
// Bike.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

class Bike implements Transport {
    public function start() {
        echo "Bike startedn";
    }

    public function stop() {
        echo "Bike Stoppedn";
    }

    public function repair() {
        echo "Bike Repairn";
    }
}

Car Class [Road Transport – Concrete Item Class]

  • Create file “Car.php”.
  • Create class “Car” and implement the “Transport” interface.
<?php
// Car.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

class Car implements Transport {
    public function start() {
        echo "Car startedn";
    }

    public function stop() {
        echo "Car Stoppedn";
    }

    public function repair() {
        echo "Car Repairn";
    }
}

Plane Class [Air Transport – Concrete Item Class]

  • Create file “Plane.php”.
  • Create class “Plane” and implement the “Transport” interface.
<?php
// Plane.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

class Plane implements Transport {
    public function start() {
        echo "Plane startedn";
    }

    public function stop() {
        echo "Plane Stoppedn";
    }

    public function repair() {
        echo "Plane Repairn";
    }
}

Helicopter Class [Air Transport – Concrete Item Class]

  • Create file “Helicopter.php”.
  • Create class “Helicopter” and implement the “Transport” interface.
<?php
// Helicopter.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

class Helicopter implements Transport {
    public function start() {
        echo "Helicopter startedn";
    }

    public function stop() {
        echo "Helicopter Stoppedn";
    }

    public function repair() {
        echo "Helicopter Repairn";
    }
}

Transport Factory [Abstract Class]

  • Create a file named “TransportFactory.php”.
  • Create abstract class “TransportFactory”..
  • Declare an abstract method named “getTransport” that returns a Transport object.
  • Define method “operateTransport” and “repairTransport”. Use the “getTransport” method to generate a transport object and use that in the functions implementations. 
<?php
// TransportFactory.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

abstract class TransportFactory {
    public function operateTransport(string $name) {
        $transport = $this->getTransport($name);

        $transport->start();
        $transport->stop();
    }

    public function repairTransport(string $name) {
        $transport = $this->getTransport($name);

        $transport->repair();
    }

    public abstract function getTransport(string $name): ?Transport;
}

Road Transport Factory

  • Create a file “RoadTransportFactory.php”.
  • Create a class “RoadTransportFactory”.
  • Extend “TransportFactory” for this class.
  • Define abstract method “getTransport”. In the implementation generate object of Car/Bike/Bus and return that.
<?php
// RoadTransportFactory.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

class RoadTransportFactory extends TransportFactory {
    public function getTransport(string $name): ?Transport {
        switch (strtolower($name)) {
            case "car":
                return new Car();
            case "bike":
                return new Bike();
            case "bus":
                return new Bus();
        }

        return null;
    }
}

Air Transport Factory

  • Create a file “AirTransportFactory.php”.
  • Create a class “AirTransportFactory”.
  • Extend “TransportFactory” for this class.
  • Define abstract method “getTransport”. In the implementation generate then object of Plane/Helicopter and return that.
<?php
// AirTransportFactory.php

namespace BigBoxCodeDesignPatternFactoryTransportMethod;

class AirTransportFactory extends TransportFactory {
    public function getTransport(string $name): ?Transport {
        switch (strtolower($name)) {
            case "plane":
                return new Plane();
            case "helicopter":
                return new Helicopter();
        }

        return null;
    }
}

Demo

To use the implementation generate an object of the RoadTransportFactory or AirTransportFactory first.

Then we can use the factory and call the methods. We need to pass the identifier(string “bus”, “helicopter” etc.) for the object that we want to use.

<?php
// demo.php

require __DIR__ . '/../../vendor/autoload.php';

use BigBoxCodeDesignPatternFactoryTransportMethodAirTransportFactory;
use BigBoxCodeDesignPatternFactoryTransportMethodRoadTransportFactory;

$roadTransportFactory = new RoadTransportFactory();
$airTransportFactory = new AirTransportFactory();

$roadTransportFactory->operateTransport("bus");

$airTransportFactory->operateTransport("helicopter");

$roadTransportFactory->repairTransport("bike");

Output

Output will be as below.

Bus started
Bus Stopped

Helicopter started
Helicopter Stopped

Bike Repair

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Factory pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.