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

Какую проблему решают фабричные методы и фабрика в программировании?

Sobes Copilot

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

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

sobes.tech AI

Фабричные методы и фабрика решают проблему создания объектов без указания конкретного класса, который будет инстанцирован. Они предоставляют интерфейс для создания объектов в родительском классе, позволяя подклассам изменять тип создаваемых объектов.

Преимущества использования:

  • Ослабление связанности: Код, использующий фабрику, не зависит от конкретных классов, что облегчает внесение изменений и расширение системы.
  • Упрощение добавления новых типов объектов: Для добавления нового типа объекта достаточно создать новый класс, реализующий общий интерфейс, и расширить фабрику.
  • Централизация создания объектов: Логика создания объектов сосредоточена в одном месте, что делает код более понятным и поддерживаемым.

Пример c фабричным методом:

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

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

class ConcreteProductB implements Product {
    public function operation(): string {
        return "Результат работы ConcreteProductB";
    }
}

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

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

// Конкретные создатели
class ConcreteCreatorA extends Creator {
    public function factoryMethod(): Product {
        return new ConcreteProductA();
    }
}

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

// Использование
function clientCode(Creator $creator) {
    echo "Клиент: Я не знаю, с каким создателем работаю, но это все равно сработает.\n" . $creator->someOperation() . "\n\n";
}

echo "Пример с ConcreteCreatorA:\n";
clientCode(new ConcreteCreatorA());

echo "Пример с ConcreteCreatorB:\n";
clientCode(new ConcreteCreatorB());
?>

Пример c абстрактной фабрикой:

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

interface AbstractProductB {
    public function usefulFunctionB(): string;
    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string;
}

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

class ConcreteProductA2 implements AbstractProductA {
    public function usefulFunctionA(): string {
        return "Результат работы ProductA2.";
    }
}

class ConcreteProductB1 implements AbstractProductB {
    public function usefulFunctionB(): string {
        return "Результат работы ProductB1.";
    }

    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
        $result = $collaborator->usefulFunctionA();
        return "Результат работы ProductB1, взаимодействующий с ({$result})";
    }
}

class ConcreteProductB2 implements AbstractProductB {
    public function usefulFunctionB(): string {
        return "Результат работы ProductB2.";
    }

    public function anotherUsefulFunctionB(AbstractProductA $collaborator): string {
        $result = $collaborator->usefulFunctionA();
        return "Результат работы ProductB2, взаимодействующий с ({$result})";
    }
}

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

// Конкретные фабрики
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();
    }
}

// Использование
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Клиент: Тестирование со вторым типом фабрики:\n";
clientCode(new ConcreteFactory2());
?>