Разница между Abstract Factory и Factory Method в PHP
Оба паттерна относятся к порождающим (Creational) паттернам, но они решают разные задачи.
1. Factory Method (Фабричный метод)
Фабричный метод используется, когда подклассы определяют, какой конкретный объект создавать. То есть он делегирует создание объектов дочерним классам.
Признаки Factory Method:
✅ Используется в одиночном семействе объектов
✅ Создание объекта делегируется подклассу
✅ Основной класс определяет интерфейс создания, но не создает объекты напрямую
Пример Factory Method
interface Transport {
public function deliver(): string;
}
class Truck implements Transport {
public function deliver(): string {
return "Delivery by truck";
}
}
class Ship implements Transport {
public function deliver(): string {
return "Delivery by ship";
}
}
abstract class Logistics {
// Фабричный метод — он будет переопределяться в подклассах
abstract public function createTransport(): Transport;
public function planDelivery(): string {
$transport = $this->createTransport();
return $transport->deliver();
}
}
// Два разных подкласса, создающие разные объекты
class RoadLogistics extends Logistics {
public function createTransport(): Transport {
return new Truck();
}
}
class SeaLogistics extends Logistics {
public function createTransport(): Transport {
return new Ship();
}
}
// Использование
$logistics = new RoadLogistics();
echo $logistics->planDelivery(); // "Delivery by truck"
✅ Когда использовать?
Когда нужно делегировать создание объектов дочерним классам.
Когда код должен оставаться гибким и позволять изменять классы объектов, не меняя логику основного класса.
2. Abstract Factory (Абстрактная фабрика)
Абстрактная фабрика предназначена для создания целого семейства объектов, которые работают вместе. В отличие от Factory Method, этот паттерн создает не один объект, а группу взаимосвязанных объектов.
Признаки Abstract Factory:
✅ Используется в нескольких семейств объекта
✅ Возвращает разные типы объектов, но объединенные в одно семейство
✅ Позволяет переключать семейства объектов без изменения кода
Пример Abstract Factory
// 1. Интерфейсы для кнопок и чекбоксов
interface Button {
public function render(): string;
}
interface Checkbox {
public function check(): string;
}
// 2. Конкретные реализации под Windows
class WindowsButton implements Button {
public function render(): string {
return "Windows Button";
}
}
class WindowsCheckbox implements Checkbox {
public function check(): string {
return "Windows Checkbox";
}
}
// 3. Конкретные реализации под Mac
class MacButton implements Button {
public function render(): string {
return "Mac Button";
}
}
class MacCheckbox implements Checkbox {
public function check(): string {
return "Mac Checkbox";
}
}
// 4. Абстрактная фабрика
interface GUIFactory {
public function createButton(): Button;
public function createCheckbox(): Checkbox;
}
// 5. Конкретные фабрики для Windows и Mac
class WindowsFactory implements GUIFactory {
public function createButton(): Button {
return new WindowsButton();
}
public function createCheckbox(): Checkbox {
return new WindowsCheckbox();
}
}
class MacFactory implements GUIFactory {
public function createButton(): Button {
return new MacButton();
}
public function createCheckbox(): Checkbox {
return new MacCheckbox();
}
}
// 6. Клиентский код, который работает с фабриками
function renderGUI(GUIFactory $factory) {
$button = $factory->createButton();
$checkbox = $factory->createCheckbox();
echo $button->render() . "\n";
echo $checkbox->check() . "\n";
}
// Использование
$factory = new WindowsFactory();
renderGUI($factory);
// "Windows Button"
// "Windows Checkbox"
$factory = new MacFactory();
renderGUI($factory);
// "Mac Button"
// "Mac Checkbox"
✅ Когда использовать?
Когда нужно создавать целые группы объектов, которые должны работать вместе.
Когда необходимо легко переключаться между разными семействами объектов без изменения клиентского кода.
Ключевые отличия
Factory Method | Abstract Factory | |
Создает | Один объект | Группу взаимосвязанных объектов |
Гибкость | Делегирует создание объектов подклассам | Позволяет легко переключать семейства объектов |
Используется | Когда подклассы определяют, какой объект создать | Когда нужна платформа для создания множества связанных объектов |
Пример | Логистика создает либо Truck , либо Ship | Фабрика создает Button и Checkbox для Windows или Mac |
Простое правило:
Если создается один объект → используй Factory Method
Если создается целая группа объектов → используй Abstract Factory