Sobes.tech
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());
Tell us about the 'factory' design pattern and its… - sobes.tech