Middle
What problem do factory methods and factory pattern solve in programming?
sobes.tech AI
Answer from AI
Factory methods and factories solve the problem of creating objects without specifying the exact class that will be instantiated. They provide an interface for creating objects in the parent class, allowing subclasses to change the type of objects that are created.
Advantages of using:
- Reduced coupling: Code that uses the factory is not dependent on specific classes, making it easier to make changes and extend the system.
- Simplifies adding new object types: To add a new object type, it is enough to create a new class implementing a common interface and extend the factory.
- Centralized object creation: The logic for creating objects is concentrated in one place, making the code more understandable and maintainable.
Example with a factory method:
<?php
// Product interface
interface Product {
public function operation(): string;
}
// Concrete products
class ConcreteProductA implements Product {
public function operation(): string {
return "Result of ConcreteProductA";
}
}
class ConcreteProductB implements Product {
public function operation(): string {
return "Result of ConcreteProductB";
}
}
// Creator abstract class
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
return "Creator: Same logic works with " . $product->operation();
}
}
// Concrete creators
class ConcreteCreatorA extends Creator {
public function factoryMethod(): Product {
return new ConcreteProductA();
}
}
class ConcreteCreatorB extends Creator {
public function factoryMethod(): Product {
return new ConcreteProductB();
}
}
// Usage
function clientCode(Creator $creator) {
echo "Client: I don't know which creator I'm working with, but it still works.\n" . $creator->someOperation() . "\n\n";
}
echo "Example with ConcreteCreatorA:\n";
clientCode(new ConcreteCreatorA());
echo "Example with ConcreteCreatorB:\n";
clientCode(new ConcreteCreatorB());
?>
Example with an abstract factory:
<?php
// Product family interfaces
interface AbstractProductA {
public function usefulFunctionA(): string;
}
interface AbstractProductB {
public function usefulFunctionB(): string;
public function anotherUsefulFunctionB(AbstractProductA $collaborator): string;
}
// Concrete products for the first factory
class ConcreteProductA1 implements AbstractProductA {
public function usefulFunctionA(): string {
return "Result of ProductA1.";
}
}
class ConcreteProductA2 implements AbstractProductA {
public function usefulFunctionA(): string {
return "Result of ProductA2.";
}
}
class ConcreteProductB1 implements AbstractProductB {
public function usefulFunctionB(): string {
return "Result of ProductB1.";
}
public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
$result = $collaborator->usefulFunctionA();
return "Result of ProductB1 interacting with ({$result})";
}
}
class ConcreteProductB2 implements AbstractProductB {
public function usefulFunctionB(): string {
return "Result of ProductB2.";
}
public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
$result = $collaborator->usefulFunctionA();
return "Result of ProductB2 interacting with ({$result})";
}
}
// Abstract factory interface
interface AbstractFactory {
public function createProductA(): AbstractProductA;
public function createProductB(): AbstractProductB;
}
// Concrete factories
class ConcreteFactory1 implements AbstractFactory {
public function createProductA(): AbstractProductA {
return new ConcreteProductA1();
}
public function createProductB(): AbstractProductB {
return new ConcreteProductB1();
}
}
class ConcreteFactory2 implements AbstractFactory {
public function createProductA(): AbstractProductA {
return new ConcreteProductA2();
}
public function createProductB(): AbstractProductB {
return new ConcreteProductB2();
}
}
// 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 "\nClient: Testing with the second factory type:\n";
clientCode(new ConcreteFactory2());
?>