Factory Method — это порождающий паттерн проектирования, который определяет интерфейс для создания объекта, но позволяет подклассам решать, какой именно экземпляр создавать. В PHP этот паттерн широко применяется в фреймворках и библиотеках.
Что такое Factory Method и зачем он нужен?
Паттерн решает проблему создания объектов без привязки к конкретным классам. Вместо использования оператора new напрямую, вы вызываете фабричный метод, который возвращает нужный объект. Это упрощает тестирование и расширение системы.
Основные преимущества:
- Код становится гибким и легко расширяемым
- Упрощается добавление новых типов объектов
- Снижается связанность между классами
- Улучшается тестируемость кода
Реализация Factory Method в PHP
Базовый пример с интерфейсом
filePath = filePath;
public function log(string message): void {
file_put_contents(
this−>filePath,message . PHP_EOL, FILE_APPEND);
class DatabaseLogger implements Logger {
private PDO db;
public function __construct(PDO db) {
this−>db=db;
public function log(string message): void {
stmt = this->db->prepare('INSERT INTO logs (message) VALUES (?)');
stmt->execute([message]);
abstract class LoggerFactory {
abstract public function createLogger(): Logger;
class FileLoggerFactory extends LoggerFactory {
private string filePath;
public function __construct(string filePath) {
this->filePath = filePath;
public function createLogger(): Logger {
return new FileLogger(this->filePath);
class DatabaseLoggerFactory extends LoggerFactory {
private PDO db;
public function __construct(PDO db) {
this−>db=db;
public function createLogger(): Logger {
return new DatabaseLogger(this->db);
// Использование
fileFactory = new FileLoggerFactory('/var/log/app.log');
logger=fileFactory->createLogger();
logger->log('Сообщение записано в файл');
dbFactory = new DatabaseLoggerFactory(pdo);
logger = dbFactory->createLogger();
logger->log('Сообщение записано в базу');
?>Альтернативная реализация со статическим методом
new FileLogger('/var/log/app.log'),
'database' => new DatabaseLogger(self::getDbConnection()),
default => throw new \InvalidArgumentException('Неизвестный тип логгера')
};
private static function getDbConnection(): PDO {
return new PDO('mysql:host=localhost;dbname=app', 'user', 'pass');
logger = LoggerFactoryStatic::create('file');
logger->log('Создан через статический фабричный метод');
?>Когда использовать Factory Method?
| Сценарий | Пример |
|---|---|
| Библиотеки и фреймворки | Создание соединений с БД, обработчиков запросов |
| Сложные объекты с зависимостями | Объекты с множеством параметров в конструкторе |
| Тестирование | Подмена реальных объектов на моки |
| Платформенные различия | ОС-специфичные реализации |
Factory Method vs Abstract Factory
Эти паттерны часто путают. Factory Method создаёт объекты одного семейства через метод в классе. Abstract Factory создаёт семейства связанных объектов через целую фабрику.
Factory Method проще и используется чаще. Abstract Factory применяется для создания целых наборов взаимосвязанных объектов.
Практические примеры из Laravel
В Laravel Factory Method используется повсеместно. Например, метод make() в контейнере сервисов:
make(UserService::class);
?>Этот паттерн делает код Laravel невероятно гибким и тестируемым.
Итог
Factory Method — один из самых полезных паттернов в PHP. Он помогает писать чистый, слабосвязанный и легко тестируемый код. Начните с простого фабричного метода в вашем проекте уже сегодня.