Ответ
Паттерн Factory Method (Фабричный метод) — это порождающий шаблон, который определяет общий интерфейс для создания объектов в суперклассе, позволяя подклассам изменять тип создаваемых объектов.
Суть: Класс делегирует ответственность по созданию экземпляров своим подклассам.
Пример на PHP (логирование в разные каналы):
// Продукт
interface Logger {
public function log(string $message): void;
}
// Конкретные продукты
class FileLogger implements Logger {
private string $filePath;
public function __construct(string $filePath) {
$this->filePath = $filePath;
}
public function log(string $message): void {
file_put_contents($this->filePath, date('Y-m-d H:i:s') . ': ' . $message . PHP_EOL, FILE_APPEND);
}
}
class DatabaseLogger implements Logger {
private PDO $connection;
public function __construct(PDO $connection) {
$this->connection = $connection;
}
public function log(string $message): void {
$stmt = $this->connection->prepare("INSERT INTO logs (message, created_at) VALUES (?, NOW())");
$stmt->execute([$message]);
}
}
// Создатель (Creator)
abstract class LoggerFactory {
// Фабричный метод
abstract public function createLogger(): Logger;
// Бизнес-логика, использующая продукт
public function logMessage(string $message): void {
$logger = $this->createLogger();
$logger->log($message);
echo "Message logged via " . get_class($logger) . "n";
}
}
// Конкретные создатели
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 $connection;
public function __construct(PDO $connection) {
$this->connection = $connection;
}
public function createLogger(): Logger {
return new DatabaseLogger($this->connection);
}
}
// Использование
// Клиентский код работает с фабрикой через абстрактный тип
function clientCode(LoggerFactory $factory) {
$factory->logMessage("Application started");
}
// Конфигурация фабрики зависит от среды выполнения
if ($_ENV['LOG_CHANNEL'] === 'file') {
$factory = new FileLoggerFactory('/var/log/app.log');
} else {
$pdo = new PDO('mysql:host=localhost;dbname=app', 'user', 'pass');
$factory = new DatabaseLoggerFactory($pdo);
}
clientCode($factory);
Преимущества:
- Избегает жесткой привязки к конкретным классам продуктов в основном коде.
- Принцип единой ответственности: Код создания продукта отделен от бизнес-логики.
- Принцип открытости/закрытости: Легко ввести новые типы продуктов, создав новый подкласс создателя.
Отличие от Simple Factory: Factory Method использует наследование и полиморфизм, в то время как Simple Factory — это обычно один статический метод, который возвращает объект на основе входного параметра.