Middle
Tell us about the 'factory' design pattern and its application in PHP.
sobes.tech AI
Answer from AI
Factory (Factory Method and Abstract Factory) is a creational design pattern that provides an interface for creating objects in a superclass but allows subclasses to alter the type of objects that will be created.
Application in PHP:
- Isolation of object creation process: Allows separating the code that creates objects from the code that uses these objects. This simplifies changing the type of created objects without modifying client code.
- Creating objects based on configuration or conditions: You can use a factory to create different implementations of an interface depending on parameters passed to the factory or application settings.
- Simplifying testing: By replacing real objects with mocks or stubs in the factory during testing, dependencies can be easily controlled.
Factory Method: Defines a method for creating an object, which must be implemented in subclasses.
<?php
// Product interface
interface Product {
public function operation(): string;
}
// Concrete product A
class ConcreateProductA implements Product {
public function operation(): string {
return "Result of Product A operation";
}
}
// Concrete product B
class ConcreateProductB implements Product {
public function operation(): string {
return "Result of Product B operation";
}
}
// Creator interface
abstract class Creator {
abstract public function factoryMethod(): Product;
public function someOperation(): string {
// Call the factory method to create a product
$product = $this->factoryMethod();
// Use the product
$result = "Creator: Working with " . $product->operation();
return $result;
}
}
// Concrete Creator A
class ConcreateCreatorA extends Creator {
public function factoryMethod(): Product {
return new ConcreateProductA();
}
}
// Concrete Creator B
class ConcreateCreatorB extends Creator {
public function factoryMethod(): Product {
return new ConcreateProductB();
}
}
// Usage
// $creatorA = new ConcreateCreatorA();
// echo $creatorA->someOperation();
// $creatorB = new ConcreateCreatorB();
// echo $creatorB->someOperation();
Abstract Factory: Provides an interface for creating families of related or dependent objects without specifying their concrete classes.
<?php
// Abstract factory interface
interface AbstractFactory {
public function createProductA(): AbstractProductA;
public function createProductB(): AbstractProductB;
}
// Abstract product A interface
interface AbstractProductA {
public function usefulFunctionA(): string;
}
// Abstract product B interface
interface AbstractProductB {
public function usefulFunctionB(): string;
public function anotherUsefulFunctionB(AbstractProductA $collaborator): string;
}
// Concrete factory 1
class ConcreteFactory1 implements AbstractFactory {
public function createProductA(): AbstractProductA {
return new ConcreteProductA1();
}
public function createProductB(): AbstractProductB {
return new ConcreteProductB1();
}
}
// Concrete factory 2
class ConcreteFactory2 implements AbstractFactory {
public function createProductA(): AbstractProductA {
return new ConcreteProductA2();
}
public function createProductB(): AbstractProductB {
return new ConcreteProductB2();
}
}
// Concrete product A1
class ConcreteProductA1 implements AbstractProductA {
public function usefulFunctionA(): string {
return "Result of Product A1.";
}
}
// Concrete product A2
class ConcreteProductA2 implements AbstractProductA {
public function usefulFunctionA(): string {
return "Result of Product A2.";
}
}
// Concrete product B1
class ConcreteProductB1 implements AbstractProductB {
public function usefulFunctionB(): string {
return "Result of Product B1.";
}
public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
$result = $collaborator->usefulFunctionA();
return "Result of Product B1 working with (" . $result . ")";
}
}
// Concrete product B2
class ConcreteProductB2 implements AbstractProductB {
public function usefulFunctionB(): string {
return "Result of Product B2.";
}
public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
$result = $collaborator->usefulFunctionA();
return "Result of Product B2 working with (" . $result . ")";
}
}
// Usage
// function clientCode(AbstractFactory $factory) {
// $productA = $factory->createProductA();
// $productB = $factory->createProductB();
// echo $productB->usefulFunctionB() . "\n";
// echo $productB->anotherUsefulFunctionB($productA) . "\n";
// }
//
// echo "Client: Testing with the first factory type:\n";
// clientCode(new ConcreteFactory1());
//
// echo "Client: Testing with the second factory type:\n";
// clientCode(new ConcreteFactory2());