The Factory Method pattern is a design pattern that defines an interface for creating objects but allows subclasses to alter the type of objects that will be created. This pattern helps in delegating the instantiation logic to subclasses, promoting loose coupling and making it easier to introduce new types of objects without altering existing code.

Key Characteristics:

  • Defers Instantiation: The creation of objects is deferred to subclasses.
  • Encapsulation: Encapsulates object creation and allows subclasses to provide specific implementations.
  • Flexibility: Provides flexibility in choosing the type of object to create.

How It Works:

  1. Product Interface: Define an interface or abstract class for the type of object that will be created.
  2. Concrete Products: Implement concrete classes that adhere to the product interface.
  3. Creator: Define an abstract class or interface with a factory method for creating products.
  4. Concrete Creator: Implement concrete classes that override the factory method to return instances of specific products.

Example in PHP:

  // Product Interface
interface Product {
    public function operation();
}

// Concrete Product A
class ConcreteProductA implements Product {
    public function operation() {
        return "ConcreteProductA";
    }
}

// Concrete Product B
class ConcreteProductB implements Product {
    public function operation() {
        return "ConcreteProductB";
    }
}

// Creator Abstract Class
abstract class Creator {
    // Factory method
    abstract public function factoryMethod(): Product;

    // Some operation that uses the factory method
    public function someOperation() {
        $product = $this->factoryMethod();
        return $product->operation();
    }
}

// Concrete Creator A
class ConcreteCreatorA extends Creator {
    public function factoryMethod(): Product {
        return new ConcreteProductA();
    }
}

// Concrete Creator B
class ConcreteCreatorB extends Creator {
    public function factoryMethod(): Product {
        return new ConcreteProductB();
    }
}

// Usage
$creatorA = new ConcreteCreatorA();
echo $creatorA->someOperation(); // Output: ConcreteProductA

$creatorB = new ConcreteCreatorB();
echo $creatorB->someOperation(); // Output: ConcreteProductB
  

Explanation:

  1. Product Interface: Defines a common interface for all products (Product).
  2. Concrete Products: ConcreteProductA and ConcreteProductB implement the Product interface.
  3. Creator: An abstract class (Creator) declares the factory method (factoryMethod) which is meant to be overridden by concrete creators.
  4. Concrete Creators: ConcreteCreatorA and ConcreteCreatorB implement the factory method to create instances of ConcreteProductA and ConcreteProductB, respectively.

Benefits:

  • Loose Coupling: The client code is decoupled from the specific classes that implement the product. It relies on abstractions rather than concrete implementations.
  • Flexibility: New types of products can be added without modifying the client code, only by creating new concrete creators and products.
  • Encapsulation: Encapsulates object creation logic, centralizing the instantiation process.

Use Cases:

  • UI Libraries: To create different UI components (buttons, dialogs) depending on the operating system or theme.
  • Document Processing: To create different types of documents (PDF, Word) depending on the required format.

The Factory Method pattern is useful for scenarios where the exact type of object to be created is determined by the subclass or external factors, promoting a flexible and extensible design.