Что это такое
Паттерн Фабричный метод прячет создание объекта за функцией. Вызывающий код говорит, что ему нужно, — фабрика решает, какой конкретный класс создать, и возвращает его как интерфейс.
Вызывающий код никогда не обращается к конкретным классам, поэтому новые виды можно добавлять, не меняя ни строчки в вызывающем коде. В PHP это просто функция newSomething() — или статический метод класса, — которая возвращает интерфейс.
Пример: фабрика хранилищ
newStorage("disk") и newStorage("memory") возвращают разные конкретные классы за одним и тем же интерфейсом Storage — вызывающий код не видит разницы, и ему это не нужно.
Фабрика выбирает класс
Конструкция match по видам находится в одном месте — в фабрике. Остальная программа знает только интерфейс.
Вывод: PHP-скрипт
<?php
interface Storage {
public function save(string $data): string;
}
class DiskStore implements Storage {
public function save(string $data): string {
return "disk: сохранено " . $data;
}
}
class MemoryStore implements Storage {
public function save(string $data): string {
return "memory: оставлено в памяти " . $data;
}
}
// Фабрика решает, какой конкретный класс создать.
function newStorage(string $kind): Storage {
return match ($kind) {
"memory" => new MemoryStore(),
default => new DiskStore(),
};
}
foreach (["disk", "memory"] as $kind) {
$s = newStorage($kind);
echo $s->save("order #1042"), "\n";
}
Когда его применять
Применяйте, когда конкретный класс зависит от того, что известно только во время выполнения, — от значения конфигурации, выбора пользователя, окружения, — или когда логику создания нужно держать ровно в одном месте.
Не применяйте, когда реализация только одна и второй не предвидится. Для $store = new DiskStore() фабрика не нужна.
Плюсы и минусы
Плюсы: логика создания в одном месте; вызывающий код зависит только от интерфейса; добавление нового вида затрагивает только фабрику.
Минусы: ещё один слой, через который приходится читать код; при единственной реализации это чистая формальность.