Назад к вопросам
Middle
102
questionbank

Расскажите о паттерне проектирования 'фабрика' и его применении в PHP.

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Фабрика (Factory Method и Abstract Factory) — это порождающий паттерн проектирования, который предоставляет интерфейс для создания объектов в суперклассе, но позволяет подклассам изменять тип создаваемых объектов.

Применение в PHP:

  • Изоляция процесса создания объектов: Позволяет отделить код, создающий объекты, от кода, использующего эти объекты. Это упрощает изменение типа создаваемых объектов без изменения клиентского кода.
  • Создание объектов на основе конфигурации или условий: Можно использовать фабрику для создания различных реализаций одного интерфейса в зависимости от параметров, переданных в фабрику, или настроек приложения.
  • Упрощение тестирования: Заменяя реальные объекты моками или заглушками в фабрике при тестировании, можно легко контролировать зависимости.

Factory Method: Определяет метод создания объекта, который должен быть реализован в подклассах.

<?php
// Интерфейс продукта
interface Product {
    public function operation(): string;
}

// Конкретный продукт A
class ConcreateProductA implements Product {
    public function operation(): string {
        return "Результат операции продукта A";
    }
}

// Конкретный продукт B
class ConcreateProductB implements Product {
    public function operation(): string {
        return "Результат операции продукта B";
    }
}

// Интерфейс создателя
abstract class Creator {
    abstract public function factoryMethod(): Product;

    public function someOperation(): string {
        // Вызов фабричного метода для создания объекта
        $product = $this->factoryMethod();
        // Использование объекта
        $result = "Создатель: Работаю с " . $product->operation();
        return $result;
    }
}

// Конкретный создатель A
class ConcreateCreatorA extends Creator {
    public function factoryMethod(): Product {
        return new ConcreateProductA();
    }
}

// Конкретный создатель B
class ConcreateCreatorB extends Creator {
    public function factoryMethod(): Product {
        return new ConcreateProductB();
    }
}

// Использование
// $creatorA = new ConcreateCreatorA();
// echo $creatorA->someOperation();
// $creatorB = new ConcreateCreatorB();
// echo $creatorB->someOperation();

Abstract Factory: Предоставляет интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов.

<?php
// Интерфейс абстрактной фабрики
interface AbstractFactory {
    public function createProductA(): AbstractProductA;
    public function createProductB(): AbstractProductB;
}

// Интерфейс абстрактного продукта A
interface AbstractProductA {
    public function usefulFunctionA(): string;
}

// Интерфейс абстрактного продукта B
interface AbstractProductB {
    public function usefulFunctionB(): string;
    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string;
}

// Конкретная фабрика 1
class ConcreteFactory1 implements AbstractFactory {
    public function createProductA(): AbstractProductA {
        return new ConcreteProductA1();
    }

    public function createProductB(): AbstractProductB {
        return new ConcreteProductB1();
    }
}

// Конкретная фабрика 2
class ConcreteFactory2 implements AbstractFactory {
    public function createProductA(): AbstractProductA {
        return new ConcreteProductA2();
    }

    public function createProductB(): AbstractProductB {
        return new ConcreteProductB2();
    }
}

// Конкретный продукт A1
class ConcreteProductA1 implements AbstractProductA {
    public function usefulFunctionA(): string {
        return "Результат продукта A1.";
    }
}

// Конкретный продукт A2
class ConcreteProductA2 implements AbstractProductA {
    public function usefulFunctionA(): string {
        return "Результат продукта A2.";
    }
}

// Конкретный продукт B1
class ConcreteProductB1 implements AbstractProductB {
    public function usefulFunctionB(): string {
        return "Результат продукта B1.";
    }

    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
        $result = $collaborator->usefulFunctionA();
        return "Результат продукта B1, работающего с (" . $result . ")";
    }
}

// Конкретный продукт B2
class ConcreteProductB2 implements AbstractProductB {
    public function usefulFunctionB(): string {
        return "Результат продукта B2.";
    }

    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
        $result = $collaborator->usefulFunctionA();
        return "Результат продукта B2, работающего с (" . $result . ")";
    }
}

// Использование
// function clientCode(AbstractFactory $factory) {
//     $productA = $factory->createProductA();
//     $productB = $factory->createProductB();
//     echo $productB->usefulFunctionB() . "\n";
//     echo $productB->anotherUsefulFunctionB($productA) . "\n";
// }
//
// echo "Клиент: Тестирование с первым типом фабрики:\n";
// clientCode(new ConcreteFactory1());
//
// echo "Клиент: Тестирование со вторым типом фабрики:\n";
// clientCode(new ConcreteFactory2());