🧩 Factory Method Pattern
✅ Intent
- Delegate "which class to instantiate" to subclasses
- Centralize object creation to improve flexibility and extensibility
✅ Motivation
- Manage shared utilities like
Logger
using a common factory method - Simplifies switching implementations or injecting mocks
✅ When to Use
- When you need to switch the concrete class based on version or conditions
- When designing for extensibility at the framework level
✅ Code Example
- TypeScript
- PHP
- Python
class Logger {
log(message: string) {
console.log(`[LOG]: ${message}`);
}
}
// Creator(抽象クラス)
abstract class UserService {
protected logger: Logger;
constructor() {
this.logger = this.createLogger(); // Factory Method を呼ぶ
}
protected abstract createLogger(): Logger;
createUser(name: string) {
this.logger.log(`ユーザー作成: ${name}`);
}
}
// ConcreteCreator
class DefaultUserService extends UserService {
protected createLogger(): Logger {
return new Logger();
}
}
// 利用例
const service = new DefaultUserService();
service.createUser("Hiroshi");
<?php
class Logger {
public function log(string $message): void {
echo "[LOG]: {$message}\n";
}
}
// Creator(抽象クラス)
abstract class UserService {
protected Logger $logger;
public function __construct() {
$this->logger = $this->createLogger();
}
abstract protected function createLogger(): Logger;
public function createUser(string $name): void {
$this->logger->log("ユーザー作成: {$name}");
}
}
// ConcreteCreator
class DefaultUserService extends UserService {
protected function createLogger(): Logger {
return new Logger();
}
}
// 利用例
$service = new DefaultUserService();
$service->createUser("Hiroshi");
from abc import ABC, abstractmethod
class Logger:
def log(self, message: str):
print(f"[LOG]: {message}")
# Creator(抽象クラス)
class UserService(ABC):
def __init__(self):
self.logger = self.create_logger()
@abstractmethod
def create_logger(self) -> Logger:
pass
def create_user(self, name: str):
self.logger.log(f"ユーザー作成: {name}")
# ConcreteCreator
class DefaultUserService(UserService):
def create_logger(self) -> Logger:
return Logger()
# 利用例
service = DefaultUserService()
service.create_user("Hiroshi")
✅ Explanation
This code applies the Factory Method
pattern to delegate the responsibility of object creation to subclasses.
The Factory Method
pattern encapsulates the creation logic, allowing subclasses to customize the instantiation process.
1. Overview of the Factory Method Pattern
-
Creator: Defines an abstract method (
Factory Method
) responsible for object creation- Represented by
UserService
in this code
- Represented by
-
ConcreteCreator: Implements the
Factory Method
and provides the actual instantiation logic- Represented by
DefaultUserService
- Represented by
-
Product: The object created by the factory method
- Represented by
Logger
- Represented by
2. Key Classes and Their Roles
-
Logger
- The concrete product created by the factory method
- Provides logging functionality
-
UserService
- The
Creator
class - Declares the abstract method
createLogger
and delegates the creation logic to subclasses - Uses
Logger
within thecreateUser
method
- The
-
DefaultUserService
- The
ConcreteCreator
class - Implements
createLogger
and returns a concrete instance ofLogger
- The
3. UML Class Diagram
4. Benefits of the Factory Method Pattern
- Customizable Creation Logic: Subclasses can override the factory method to control which object gets instantiated
- Loose Coupling: The
Creator
class does not depend on concreteProduct
classes, enabling better extensibility - Reusability: Centralizing instantiation via a factory method promotes consistent and reusable creation logic
This design separates the responsibility of object creation and makes the instantiation process more flexible.
It is especially useful when the created objects may vary or when the creation logic becomes complex.