Какую задачу решает паттерн ‘Абстрактная фабрика’?

«Какую задачу решает паттерн ‘Абстрактная фабрика’?» — вопрос из категории Паттерны, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Почему это важно? Позволяет легко заменять целые семейства продуктов (например, переключить UI с Windows-стиля на macOS-стиль), не меняя клиентский код, который от них зависит.

Пример на PHP:

// Абстрактные продукты
interface Button { public function render(): string; }
interface Checkbox { public function render(): string; }

// Конкретные продукты для Windows
class WinButton implements Button {
    public function render(): string { return "<button style='windows'>Click</button>"; }
}
class WinCheckbox implements Checkbox {
    public function render(): string { return "<input type='checkbox' style='windows'>"; }
}

// Конкретные продукты для macOS
class MacButton implements Button {
    public function render(): string { return "<button style='macos'>Click</button>"; }
}
class MacCheckbox implements Checkbox {
    public function render(): string { return "<input type='checkbox' style='macos'>"; }
}

// Абстрактная фабрика
interface GUIFactory {
    public function createButton(): Button;
    public function createCheckbox(): Checkbox;
}

// Конкретные фабрики
class WinFactory implements GUIFactory {
    public function createButton(): Button { return new WinButton(); }
    public function createCheckbox(): Checkbox { return new WinCheckbox(); }
}
class MacFactory implements GUIFactory {
    public function createButton(): Button { return new MacButton(); }
    public function createCheckbox(): Checkbox { return new MacCheckbox(); }
}

// Клиентский код
function createUI(GUIFactory $factory) {
    $button = $factory->createButton();
    $checkbox = $factory->createCheckbox();
    return $button->render() . "n" . $checkbox->render();
}

// Создание UI для выбранной платформы
$platform = 'mac';
$factory = $platform === 'win' ? new WinFactory() : new MacFactory();
echo createUI($factory);

Практическое применение: Часто используется в фреймворках (например, для создания кроссплатформенных UI-компонентов или подключения к разным типам баз данных в одном приложении).