Ответ
Оба паттерна относятся к порождающим и инкапсулируют создание объектов, но решают разные задачи.
Фабричный метод (Factory Method)
Цель: Делегировать создание одного конкретного продукта подклассам. Определяет интерфейс для создания объекта, но позволяет подклассам изменять тип создаваемого объекта.
Аналогия: Компания по производству мебели имеет общий цех (Creator), но в разных филиалах (ConcreteCreator) решают, какой конкретно стул (Product) производить: офисный или кухонный.
Пример на PHP (Логирование):
// Продукт
interface Logger {
public function log(string $message): void;
}
class FileLogger implements Logger {
public function log(string $message): void {
file_put_contents('app.log', $message, FILE_APPEND);
}
}
class DatabaseLogger implements Logger {
public function log(string $message): void {
// Логика сохранения в БД
echo "Log to DB: $message";
}
}
// Создатель с фабричным методом
abstract class LoggerCreator {
// ФАБРИЧНЫЙ МЕТОД — абстрактный, реализация у наследников
abstract public function createLogger(): Logger;
public function logMessage(string $message): void {
$logger = $this->createLogger(); // Используем фабричный метод
$logger->log($message);
}
}
// Конкретные создатели
class FileLoggerCreator extends LoggerCreator {
public function createLogger(): Logger {
return new FileLogger();
}
}
class DatabaseLoggerCreator extends LoggerCreator {
public function createLogger(): Logger {
return new DatabaseLogger();
}
}
// Использование
$creator = new FileLoggerCreator();
$creator->logMessage('Test message'); // Будет записано в файл
Абстрактная фабрика (Abstract Factory)
Цель: Создание семейств взаимосвязанных или взаимозависимых продуктов (например, UI-элементов одной ОС). Гарантирует совместимость продуктов.
Аналогия: Компания производит полные гарнитуры мебели (AbstractFactory): в викторианском стиле (VictorianFactory) — стул, стол, диван одного стиля; в современном (ModernFactory) — другой набор.
Пример на PHP (UI-виджеты):
// Абстрактные продукты
interface Button { public function render(): string; }
interface Checkbox { public function render(): string; }
// Конкретные продукты для Windows
class WinButton implements Button {
public function render(): string { return "<button>Windows Button</button>"; }
}
class WinCheckbox implements Checkbox {
public function render(): string { return "<checkbox>Windows Checkbox</checkbox>"; }
}
// Конкретные продукты для MacOS
class MacButton implements Button {
public function render(): string { return "<button>MacOS Button</button>"; }
}
class MacCheckbox implements Checkbox {
public function render(): string { return "<checkbox>MacOS Checkbox</checkbox>"; }
}
// АБСТРАКТНАЯ ФАБРИКА — создаёт семейство продуктов
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 renderUI(GUIFactory $factory): void {
$button = $factory->createButton();
$checkbox = $factory->createCheckbox();
echo $button->render() . ' ' . $checkbox->render();
}
// Все элементы будут в одном стиле
renderUI(new WinFactory()); // <button>Windows Button</button> <checkbox>Windows Checkbox</checkbox>
renderUI(new MacFactory()); // <button>MacOS Button</button> <checkbox>MacOS Checkbox</checkbox>
Итоговое отличие:
- Фабричный метод создаёт один продукт, а способ его создания варьируется наследниками.
- Абстрактная фабрика создаёт целое семейство совместимых продуктов, инкапсулируя выбор целого семейства.
Ответ 18+ 🔞
Давай разжую тебе эту тему про фабрики, а то я вижу, у тебя в глазах уже квадратные скобки плывут. Слушай сюда, это как сравнивать поход в столовую за одним конкретным борщом и заказ комплексного обеда, где всё на одной тарелке и сочетается.
Фабричный метод — это как заказать одно блюдо, но в разных забегаловках.
Суть в чём, ёпта? Есть у тебя общая идея — «надо что-то залогировать». Это наш LoggerCreator. А вот как именно это сделать — нахуярить в файл или в базу данных — решают уже его наследнички. Они переопределяют один-единственный метод createLogger(). Всё, больше от них ничего не надо.
// Вот смотри, абстрактный создатель. Он говорит: "Дети, я не ебу, какой логгер вам нужен, сделайте сами".
abstract class LoggerCreator {
abstract public function createLogger(): Logger; // Вот этот самый фабричный метод, его реализуют дети.
public function logMessage(string $message): void {
$logger = $this->createLogger(); // А тут он просто пользуется тем, что ребёнок ему подсунул.
$logger->log($message);
}
}
Короче, если тебе нужно разнообразить создание одного объекта — это твой выбор. Один продукт, много способов его сварганить. Довольно просто, терпения ноль ебать на понимание.
Абстрактная фабрика — это уже не шутки, это целый стиль жизни, семейство продуктов.
Тут задача посерьёзнее. Представь, что ты делаешь интерфейс. И тебе надо, чтобы все кнопки, чекбоксы и ползунки были в одном стиле — либо все «под винду», либо все «под мак». Если смешать — будет пиздец и хитрая жопа, пользователь глаза сломает.
Вот тут в игру входит абстрактная фабрика. Это уже не один метод, а целый интерфейс с кучей методов, каждый из которых создаёт свой продукт из семейства.
// Это контракт на целый комплект.
interface GUIFactory {
public function createButton(): Button;
public function createCheckbox(): Checkbox;
// ... и так далее, для всех виджетов
}
// Конкретная фабрика для Windows. Она, блядь, как конвейер, штампует только виндовые детали.
class WinFactory implements GUIFactory {
public function createButton(): Button { return new WinButton(); } // Только WinButton!
public function createCheckbox(): Checkbox { return new WinCheckbox(); } // Только WinCheckbox!
}
Клиентский код (renderUI) получает фабрику и, не парится, создаёт через неё всё, что нужно. Он абсолютно не ебёт, какие там конкретные классы кнопок и чекбоксов. Главное — они все будут от одной фабрики, а значит, в одном стиле. Гарантия совместимости, доверия ебать ноль, но система работает.
Итоговая разница, если по-простому:
- Фабричный метод: «Эй, наследник, скажи мне, какой один объект мне тут нужно создать, а я дальше сам им воспользуюсь». Фокус на делегировании создания одного продукта.
- Абстрактная фабрика: «Эй, фабрика, мне нужен полный комплект связанных между собой объектов (кнопка, чекбокс, меню), и чтобы всё было в одном стиле». Фокус на создании семейств совместимых продуктов.
Выбирай, исходя из задачи. Нужно варьировать один ингредиент — фабричный метод. Нужно гарантировать, что весь интерфейс будет выдержан в одном стиле — абстрактная фабрика, ёбана в рот. Всё гениальное просто, хотя с первого взгляда охуеть можно.