Factory Method переносить рішення про створення конкретного об'єкта у підкласи. Базовий клас задає загальний алгоритм, а який саме об'єкт створити - вирішує нащадок.
Яку проблему вирішує
Частина алгоритму стабільна й однакова для всіх випадків, але конкретний продукт залежить від контексту чи типу. Якщо вшити вибір прямо в базовий клас через if/switch, кожен новий тип потребуватиме правок цього класу - порушення принципу відкритості/закритості.
Як вирішує
Базовий клас викликає абстрактний фабричний метод, не знаючи, що саме той поверне. Нащадок перевизначає метод і створює потрібний продукт. Загальний алгоритм лишається в одному місці, а розширення відбувається додаванням нового підкласу, без змін наявного коду.
interface ReportContract
{
public function render(): array;
}
abstract class ReportCreator
{
public function handle(): array
{
$report = $this->makeReport();
return $report->render();
}
abstract protected function makeReport(): ReportContract;
}
class SalesReport implements ReportContract
{
public function render(): array
{
return ['sales' => 1000];
}
}
class SalesReportCreator extends ReportCreator
{
protected function makeReport(): ReportContract
{
return new SalesReport();
}
}
Де застосовувати
- Стабільний каркас алгоритму з варіативним кроком створення об'єкта.
- На відміну від Abstract Factory (сім'я узгоджених об'єктів), Factory Method відповідає за створення одного продукту.
- У Laravel схожу роль грають контейнерні біндінги та
Model::factory() для тестових даних.
Плюси та мінуси
- + Винесення створення в підкласи дотримується принципу відкритості/закритості.
- + Загальний алгоритм не дублюється між варіантами.
- − Породжує ієрархію підкласів - по одному на кожен продукт.
- − Надлишковий, якщо вибір реалізації простий і не змінюється; тоді достатньо
match чи конфіга.