Implementing Factory Method Design Pattern in PHP
Introduction
Design patterns are essential for developing robust, scalable, and maintainable code. The Factory Method Design Pattern is one of the most commonly used design patterns in object-oriented programming. It belongs to the creational design patterns category and provides a way to delegate the instantiation of objects to subclasses. In this blog, we will explore the Factory Method Design Pattern in PHP, understand its implementation, and create a mini-project to solidify our understanding.
What is the Factory Method Design Pattern?
The Factory Method Design Pattern defines an interface for creating an object but allows subclasses to alter the type of objects that will be created. It promotes loose coupling by reducing the dependency of client classes on concrete classes.
Advantages of Factory Method Design Pattern
Encapsulation: Encapsulates object creation logic.
Loose Coupling: Reduces dependency between client and concrete classes.
Scalability: Easy to introduce new products without changing existing code.
Implementing Factory Method Design Pattern in PHP
Let's dive into the implementation of the Factory Method Design Pattern in PHP.
Step 1: Define a Product Interface
We start by defining an interface for the products that our factory will create.
<?php
interface Product {
public function getName(): string;
}
Step 2: Create Concrete Products
Next, we create concrete classes that implement the Product
interface.
<?php
class ConcreteProductA implements Product {
public function getName(): string {
return "Product A";
}
}
class ConcreteProductB implements Product {
public function getName(): string {
return "Product B";
}
}
Step 3: Define the Creator Abstract Class
The Creator
abstract class declares the factory method that returns a Product
object. Subclasses will override this method to provide specific implementations.
<?php
abstract class Creator {
abstract public function factoryMethod(): Product;
public function someOperation(): string {
$product = $this->factoryMethod();
return "Creator: The same creator's code has just worked with " . $product->getName();
}
}
Step 4: Implement Concrete Creators
Concrete creators override the factory method to create specific products.
<?php
class ConcreteCreatorA extends Creator {
public function factoryMethod(): Product {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
public function factoryMethod(): Product {
return new ConcreteProductB();
}
}
Step 5: Client Code
The client code works with an instance of a concrete creator, albeit through its base interface. As long as the client keeps working with the creator via the base interface, you can pass it any creator's subclass.
<?php
function clientCode(Creator $creator) {
echo "Client: I'm not aware of the creator's class, but it still works.\n";
echo $creator->someOperation();
}
echo "App: Launched with the ConcreteCreatorA.\n";
clientCode(new ConcreteCreatorA());
echo "\n\n";
echo "App: Launched with the ConcreteCreatorB.\n";
clientCode(new ConcreteCreatorB());
Detailed Explanation
Let's break down the code snippets and understand each part.
Product Interface
The Product
interface defines the methods that all concrete products must implement. In this case, it includes a single method getName()
.
Concrete Products
Concrete product classes (ConcreteProductA
and ConcreteProductB
) implement the Product
interface. Each class provides its own implementation of the getName()
method.
Creator Abstract Class
The Creator
abstract class declares the factoryMethod()
which must return an object of type Product
. It also includes a method someOperation()
that demonstrates how the product created by the factory method can be used.
Concrete Creators
Concrete creator classes (ConcreteCreatorA
and ConcreteCreatorB
) extend the Creator
abstract class and override the factoryMethod()
to create specific products.
Client Code
The client code uses the Creator
interface to work with concrete creators. It calls the someOperation()
method, which in turn calls the factoryMethod()
to create a product.
Mini Project: Shape Factory
To further solidify our understanding, let's create a mini project using the Factory Method Design Pattern. We will implement a Shape Factory that creates different types of shapes (Circle, Square, Rectangle).
Step 1: Define the Shape Interface
<?php
interface Shape {
public function draw(): string;
}
Step 2: Create Concrete Shapes
<?php
class Circle implements Shape {
public function draw(): string {
return "Drawing a Circle";
}
}
class Square implements Shape {
public function draw(): string {
return "Drawing a Square";
}
}
class Rectangle implements Shape {
public function draw(): string {
return "Drawing a Rectangle";
}
}
Step 3: Define the Shape Creator Abstract Class
<?php
abstract class ShapeCreator {
abstract public function factoryMethod(): Shape;
public function render(): string {
$shape = $this->factoryMethod();
return $shape->draw();
}
}
Step 4: Implement Concrete Shape Creators
<?php
class CircleCreator extends ShapeCreator {
public function factoryMethod(): Shape {
return new Circle();
}
}
class SquareCreator extends ShapeCreator {
public function factoryMethod(): Shape {
return new Square();
}
}
class RectangleCreator extends ShapeCreator {
public function factoryMethod(): Shape {
return new Rectangle();
}
}
Step 5: Client Code
<?php
function clientCode(ShapeCreator $creator) {
echo $creator->render() . "\n";
}
echo "Client: Let's draw a Circle.\n";
clientCode(new CircleCreator());
echo "\n";
echo "Client: Let's draw a Square.\n";
clientCode(new SquareCreator());
echo "\n";
echo "Client: Let's draw a Rectangle.\n";
clientCode(new RectangleCreator());
Detailed Explanation
Let's break down the mini project code and understand each part.
Shape Interface
The Shape
interface defines the methods that all concrete shapes must implement. In this case, it includes a single method draw()
.
Concrete Shapes
Concrete shape classes (Circle
, Square
, and Rectangle
) implement the Shape
interface. Each class provides its own implementation of the draw()
method.
Shape Creator Abstract Class
The ShapeCreator
abstract class declares the factoryMethod()
which must return an object of type Shape
. It also includes a method render()
that demonstrates how the shape created by the factory method can be used.
Concrete Shape Creators
Concrete shape creator classes (CircleCreator
, SquareCreator
, and RectangleCreator
) extend the ShapeCreator
abstract class and override the factoryMethod()
to create specific shapes.
Client Code
The client code uses the ShapeCreator
interface to work with concrete shape creators. It calls the render()
method, which in turn calls the factoryMethod()
to create a shape and draw it.
Conclusion
The Factory Method Design Pattern is a powerful tool for creating objects in a flexible and scalable way. By following the principles of this pattern, you can ensure that your code is easy to maintain and extend. In this blog, we have explored the implementation of the Factory Method Design Pattern in PHP, understood each part with detailed code snippets, and created a mini project to solidify our understanding. We hope this comprehensive guide helps you in mastering the Factory Method Design Pattern in your PHP projects.
Subscribe to my newsletter
Read articles from Kartik Mehta directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Kartik Mehta
Kartik Mehta
A code dependent life form.