Abstract factory pattern is used when we need multiple factories which produce related but different sets of objects. This pattern is generally used in relatively larger applications that deal with lots of classes of related classes but can be divided into multiple groups based on some criteria.
As Abstract factory pattern is a factory of the Factory pattern, so before learning the details of the Abstract factory pattern make sure to have a clear idea about Factory pattern.
This article discusses the Abstract Factory pattern implementations in PHP. Check the implementation details and examples.
Implementation
Use the following steps for the implementation-
- Create interface for the item/product classes.
- Create item/product classes and implement the item interface.
- Create an abstract factory. This can be an interface or abstract class. This has the declaration of method which are responsible for generating item/product objects.
- Create factory classes and implement the abstract factory interface/class. These classes contain method for generating item/product objects.
- Create a factory producer class. This class is responsible for generating a factory object and returning that.
Here is a simple Abstract factory implementation in PHP. This is not any specific example, just demo/sample code.
<?php
// Abstract factory implementation in PHP
// Item interface
interface ItemInterface {
function operation1(): void;
function operation2(): void;
}
// Item of type 1
class Type1Item1 implements ItemInterface {
public function operation1(): void {
echo "Type 1 Item 1: executing operation 1\n";
}
public function operation2(): void {
echo "Type 1 Item 1: executing operation 2\n";
}
}
// Item of type 1
class Type1Item2 implements ItemInterface {
public function operation1(): void {
echo "Type 1 Item 2: executing operation 1\n";
}
public function operation2(): void {
echo "Type 1 Item 2: executing operation 2\n";
}
}
// Item of type 2
class Type2Item1 implements ItemInterface {
public function operation1(): void {
echo "Type 2 Item 1: executing operation 1\n";
}
public function operation2(): void {
echo "Type 2 Item 1: executing operation 2\n";
}
}
// Item of type 2
class Type2Item2 implements ItemInterface {
public function operation1(): void {
echo "Type 2 Item 2: executing operation 1\n";
}
public function operation2(): void {
echo "Type 2 Item 2: executing operation 2\n";
}
}
// Factory interface
interface FactoryInterface {
function getItem(string $type): ?ItemInterface;
}
// Type 1 factory
class Type1Factory implements FactoryInterface {
public function getItem(string $itemIdentifier): ?ItemInterface {
switch (strtolower($itemIdentifier)) {
case "item1": return new Type1Item1();
case "item2": return new Type1Item2();
}
return null;
}
}
// Type 2 factory
class Type2Factory implements FactoryInterface {
public function getItem(string $itemIdentifier): ?ItemInterface {
switch (strtolower($itemIdentifier)) {
case "item1": return new Type2Item1();
case "item2": return new Type2Item2();
}
return null;
}
}
// Factory producer - Factory of Factory
class FactoryProducer {
public static function getFactory(int $type): ?FactoryInterface {
switch ($type) {
case 1: return new Type1Factory();
case 2: return new Type2Factory();
}
return null;
}
}
// Demo
$factory1 = FactoryProducer::getFactory(1);
$item1 = $factory1->getItem("item1");
$item1->operation1();
$item1->operation2();
$factory2 = FactoryProducer::getFactory(2);
$item2 = $factory2->getItem("item1");
$item2->operation1();
$item3 = $factory2->getItem("item2");
$item3->operation1();
$item3->operation2();
Above code will generate the following output:
Type 1 Item 1: executing operation 1
Type 1 Item 1: executing operation 2
Type 2 Item 1: executing operation 1
Type 2 Item 2: executing operation 1
Type 2 Item 2: executing operation 2
Examples
Let’s look at a few examples of Abstract factory pattern implementation in PHP.
Example #1: Transport
Here we have 2 types of transport – two and four wheelers. We want some factory mechanism for generating transport objects.
As the object generation process of different types of transports can be different, so we want to use separate factories for different types of objects.
Transport Interface [Item Interface]
- Create file “Transport.php”.
- Define interface “Transport” and declare required methods.
<?php
// Transport.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
interface Transport {
public function start(): void;
public function stop(): void;
public function repair(): void;
}
Bicycle Class [Item Class]
- Create file “Bicycle.php”.
- Create class “Bicycle”.
- Implement the “Transport” interface for the class. Define methods that are declared in the interface.
<?php
// Bicycle.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
class Bicycle implements Transport {
public function start(): void {
echo "Bicycle Started\n";
}
public function stop(): void {
echo "Bicycle Stopped\n";
}
public function repair(): void {
echo "Bicycle Repair\n";
}
}
Motorcycle Class [Item Class]
- Create file “Motorcycle.php”.
- Create “Motorcycle” class and implement “Transport” interface.
<?php
// Motorcycle.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
class Motorcycle implements Transport {
public function start(): void {
echo "Motorcycle Started\n";
}
public function stop(): void {
echo "Motorcycle Stopped\n";
}
public function repair(): void {
echo "Motorcycle Repair\n";
}
}
Car Class [Item Class]
- Create a file “Car.php”.
- Define “Car” class and implement the “Transport” interface.
<?php
// Car.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
class Car implements Transport {
public function start(): void {
echo "Car Started\n";
}
public function stop(): void {
echo "Car Stopped\n";
}
public function repair(): void {
echo "Car Repair\n";
}
}
Truck Class [Item Class]
- Create file “Truck.php”.
- Define “Truck” class and implement the “Transport” interface.
<?php
// Truck.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
class Truck implements Transport {
public function start(): void {
echo "Truck Started\n";
}
public function stop(): void {
echo "Truck Stopped\n";
}
public function repair(): void {
echo "Truck Repair\n";
}
}
Abstract Transport Factory Interface [Factory Interface]
- Create a file named “AbstractTransportFactory.php”.
- Define interface “AbstractTransportFactory”.
- Declare method “getTransport”, this takes a “$type” param and generates a factory based on that.
This can be an abstract class, if required.
The “getTransport” method can be static, if we prefer.
<?php
// AbstractTransportFactory.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
interface AbstractTransportFactory {
public function getTransport(string $type): ?Transport;
}
Two-Wheel Transport Factory Class [Factory Class]
- Create file “TwoWheelTransportFactory.php”.
- Define the class “TwoWheelTransportFactory” and implement interface “AbstractTransportFactory” for the class.
- In the “getTransport” method check the “$type” parameter and generate a two-wheel class(Bicycle, Motorcycle) object based on that.
<?php
// TwoWheelTransportFactory.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
class TwoWheelTransportFactory implements AbstractTransportFactory {
public function getTransport(string $type): ?Transport {
if (strcasecmp($type, "bicycle") === 0) {
return new Bicycle();
}
if (strcasecmp($type, "motorcycle") === 0) {
return new Motorcycle();
}
return null;
}
}
Four-Wheel Transport Factory Class [Factory Class]
- Create file “FourWheelTransportFactory.php”.
- Define the class “FourWheelTransportFactory” and implement the interface “AbstractTransportFactory” for the class.
- In the “getTransport” method check the “$type” parameter and generate a two-wheel class(Car, Truck) object based on that.
- Create a file named “four-wheel-transport-factory.ts”.
- Define factory class “FourWheelTransportFactory”, and implement “AbstractTransportFactory” for the class.
<?php
// FourWheelTransportFactory.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
class FourWheelTransportFactory implements AbstractTransportFactory {
public function getTransport(string $type): ?Transport {
if (strcasecmp($type, "car") === 0) {
return new Car();
}
if (strcasecmp($type, "truck") === 0) {
return new Truck();
}
return null;
}
}
Factory Producer Class [Producer]
- Create file “FactoryProducer.php”.
- Define class “FactoryProducer”.
- Create method “getFactory”. This method accepts param “$numberOfWheels”, and based on the number of wheels it generates an object of “TwoWheelTransportFactory” or “FourWheelTransportFactory”.
The Factory objects generated by this Factory producer will be used in the next steps to produce item/product objects.
<?php
// FactoryProducer.php
namespace BigBoxCode\DesignPattern\AbstractFactory\Transport;
class FactoryProducer {
public static function getFactory(int $numberOfWheels): ?AbstractTransportFactory {
switch ($numberOfWheels) {
case 2:
return new TwoWheelTransportFactory();
case 4:
return new FourWheelTransportFactory();
}
return null;
}
}
Demo
Use the “getFactory” method to generate a factory. And use that factory to generate transport objecs.
<?php
// demo.php
require __DIR__ . '/../../vendor/autoload.php';
use BigBoxCode\DesignPattern\AbstractFactory\Transport\FactoryProducer;
$transportFactory1 = FactoryProducer::getFactory(2);
$transport1 = $transportFactory1?->getTransport("bicycle");
$transport1?->start();
$transportFactory2 = FactoryProducer::getFactory(4);
$transport2 = $transportFactory2?->getTransport("truck");
$transport2?->start();
Output
Output of the code will be as below-
Bicycle Started
Truck Started
Source Code
Use the following link to get the source code:
Example | Source Code Link |
---|---|
Example #1: Transport | ![]() |
Other Code Implementations
Use the following links to check Abstract Factory pattern implementation in other programming languages.