🧩 Abstract Factory Pattern
✅ Intent
- Provide a single entry point to create a set of related objects (e.g., Logger + Database)
- Allow switching the entire object family depending on environment or version
✅ Motivation
- Enable swapping out multiple dependencies as a group
- Customize object instantiation based on the implementation
✅ When to Use
- When switching dependencies based on environment (e.g., staging vs production)
- When managing themes, storage providers, or other swappable components
✅ Code Example
- TypeScript
- PHP
- Python
// 製品:Logger
interface Logger {
log(message: string): void;
}
class ConsoleLogger implements Logger {
log(message: string): void {
console.log(`[LOG]: ${message}`);
}
}
// 抽象ファクトリ
interface ServiceFactory {
createLogger(): Logger;
}
// 具体ファクトリ
class DefaultServiceFactory implements ServiceFactory {
createLogger(): Logger {
return new ConsoleLogger();
}
}
// クライアント
class UserService {
private logger: Logger;
constructor(factory: ServiceFactory) {
this.logger = factory.createLogger();
}
createUser(name: string) {
this.logger.log(`ユーザー作成: ${name}`);
}
}
// 利用例
const factory = new DefaultServiceFactory();
const service = new UserService(factory);
service.createUser("Hiroshi");
<?php
// 製品インターフェース
interface Logger {
public function log(string $message): void;
}
// 製品の具象クラス
class ConsoleLogger implements Logger {
public function log(string $message): void {
echo "[LOG]: {$message}\n";
}
}
// 抽象ファクトリ
interface ServiceFactory {
public function createLogger(): Logger;
}
// 具体ファクトリ
class DefaultServiceFactory implements ServiceFactory {
public function createLogger(): Logger {
return new ConsoleLogger();
}
}
// クライアント
class UserService {
private Logger $logger;
public function __construct(ServiceFactory $factory) {
$this->logger = $factory->createLogger();
}
public function createUser(string $name): void {
$this->logger->log("ユーザー作成: {$name}");
}
}
// 利用例
$factory = new DefaultServiceFactory();
$service = new UserService($factory);
$service->createUser("Hiroshi");
from abc import ABC, abstractmethod
# 製品インターフェース
class Logger(ABC):
@abstractmethod
def log(self, message: str): pass
# 製品の具体クラス
class ConsoleLogger(Logger):
def log(self, message: str):
print(f"[LOG]: {message}")
# 抽象ファクトリ
class ServiceFactory(ABC):
@abstractmethod
def create_logger(self) -> Logger: pass
# 具体ファクトリ
class DefaultServiceFactory(ServiceFactory):
def create_logger(self) -> Logger:
return ConsoleLogger()
# クライアント
class UserService:
def __init__(self, factory: ServiceFactory):
self.logger = factory.create_logger()
def create_user(self, name: str):
self.logger.log(f"ユーザー作成: {name}")
# 利用例
factory = DefaultServiceFactory()
service = UserService(factory)
service.create_user("Hiroshi")
✅ Explanation
This code applies the Abstract Factory
pattern to delegate the creation of related objects (such as Logger
) to a factory,
thereby hiding the instantiation details from the client.
The Abstract Factory
pattern provides an interface for creating families of related objects and delegates instantiation logic to subclasses.
1. Overview of the Abstract Factory Pattern
-
AbstractFactory: Defines the interface for creating products
- Represented by
ServiceFactory
in this code
- Represented by
-
ConcreteFactory: Implements the
AbstractFactory
interface and provides the actual product creation logic- Represented by
DefaultServiceFactory
- Represented by
-
Product: The object to be created by the abstract factory
- Represented by
Logger
- Represented by
-
ConcreteProduct: The actual implementation of the product
- Represented by
ConsoleLogger
- Represented by
-
Client: Uses the
AbstractFactory
to create and consume the product- Represented by
UserService
- Represented by
2. Key Classes and Their Roles
-
Logger
- The common interface for all loggers
- Declares the method
log(message: string): void
-
ConsoleLogger
- A concrete product implementing
Logger
- Outputs log messages to the console
- A concrete product implementing
-
ServiceFactory
- The abstract factory
- Declares the method
createLogger
, which is responsible for creating aLogger
-
DefaultServiceFactory
- A concrete factory implementing
ServiceFactory
- Returns an instance of
ConsoleLogger
- A concrete factory implementing
-
UserService
- The client class
- Receives a
ServiceFactory
in its constructor and uses it to create and use aLogger
3. UML Class Diagram
4. Benefits of the Abstract Factory Pattern
- Encapsulation of Creation Logic: The client does not need to know how the product is created
- Consistent Product Creation: Related products (e.g., different types of loggers) can be created consistently
- Extensibility: New factories and products can be added without modifying existing code
This design unifies the creation of related objects and separates the creation logic from the client.
It is especially useful when multiple products are related or when the creation logic is expected to evolve.