🧩 Abstract Factory パターン
✅ 設計意図
- 関連するオブジェクト群(例:Logger + Database)をまとめて生成する窓口を作る
- 環境やバージョンごとに**「一式切り替え」**が可能
✅ 適用理由
- 複数の依存をまとめて切り替えたい
- 実装ごとにインスタンスの生成方法を変えたい
✅ 向いているシーン
- ステージング/本番環境など、環境ごとに依存関係を切り替える
- UI テーマ、ストレージプロバイダーなど
✅ コード例
- 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")
✅ 解説
このコードは Abstract Factory
パターン を使用して、関連するオブジェクト(Logger
)の生成をファクトリに委譲し、
クライアントコードから生成の詳細を隠蔽する設計を実現している。
Abstract Factory
パターンは、一連の関連オブジェクトを生成するためのインターフェースを提供し、
具体的な生成方法をサブクラスに委譲するデザインパターン。
1. Abstract Factory パターンの概要
- AbstractFactory: 製品を生成するためのインターフェースを定義
- このコードでは
ServiceFactory
が該当
- このコードでは
- ConcreteFactory:
AbstractFactory
を実装し、具体的な製品生成ロジックを提供- このコードでは
DefaultServiceFactory
が該当
- このコードでは
- Product:
AbstractFactory
によって生成されるオブジェクト- このコードでは
Logger
が該当
- このコードでは
- ConcreteProduct:
Product
を実装した具体的な製品- このコードでは
ConsoleLogger
が該当
- このコードでは
- Client:
AbstractFactory
を使用して製品を生成し、利用する- このコードでは
UserService
が該当
- このコードでは
2. 主なクラスとその役割
Logger
- 製品の共通インターフェース
log(message: string): void
メソッドを定義
ConsoleLogger
Logger
を実装した具体的な製品- コンソールにログを出力する
ServiceFactory
- 抽象ファクトリ
createLogger
メソッドを定義し、Logger
を生成する責務を持つ
DefaultServiceFactory
ServiceFactory
を実装した具体的なファクトリConsoleLogger
を生成する
UserService
- クライアントクラス
- コンストラクタで
ServiceFactory
を受け取り、Logger
を生成して利用
3. UML クラス図
4. Abstract Factory パターンの利点
- 生成の詳細を隠蔽: クライアントコードは具体的な生成ロジックを知らずに製品を利用可能
- 一貫性のある生成: 関連する製品(例: 複数の
Logger
実装)を一貫性を持って生成可能 - 拡張性: 新しいファクトリや製品を追加する場合も、既存のコードに影響を与えずに対応可能
この設計は、関連するオブジェクトの生成を統一し、生成ロジックをクライアントコードから分離する。 特に、複数の製品が関連している場合や、生成ロジックが変更される可能性がある場合に有効に機能する。