🧩 Builder パターン
✅ 設計意図
- 複雑なオブジェクトをステップごとに構築
- 同じ構築プロセスで異なる表現を作れる
✅ 適用理由
- プロパティの組み合わせが多い場合に初期化処理を見通しよく管理できる
- 一部省略可能なパラメータを順序・バリデーション付きで組み立てたい
✅ 向いているシーン
- フォームや設定オブジェクトのようにオプションが多いオブジェクトの初期化
✅ コード例
- TypeScript
- PHP
- Python
class Logger {
log(message: string): void {
console.log(`[LOG]: ${message}`);
}
}
// 対象クラス
class UserService {
constructor(private logger: Logger) {}
createUser(name: string) {
this.logger.log(`ユーザー作成: ${name}`);
}
}
// Builder
class UserServiceBuilder {
private logger: Logger | null = null;
setLogger(logger: Logger): this {
this.logger = logger;
return this;
}
build(): UserService {
if (!this.logger) {
throw new Error("Logger is required");
}
return new UserService(this.logger);
}
}
// 利用例
const builder = new UserServiceBuilder();
const service = builder.setLogger(new Logger()).build();
service.createUser("Hiroshi");
<?php
class Logger {
public function log(string $message): void {
echo "[LOG]: {$message}\n";
}
}
class UserService {
public function __construct(private Logger $logger) {}
public function createUser(string $name): void {
$this->logger->log("ユーザー作成: {$name}");
}
}
class UserServiceBuilder {
private ?Logger $logger = null;
public function setLogger(Logger $logger): self {
$this->logger = $logger;
return $this;
}
public function build(): UserService {
if (!$this->logger) {
throw new Exception("Logger is required");
}
return new UserService($this->logger);
}
}
// 利用例
$builder = new UserServiceBuilder();
$service = $builder->setLogger(new Logger())->build();
$service->createUser("Hiroshi");
class Logger:
def log(self, message: str):
print(f"[LOG]: {message}")
class UserService:
def __init__(self, logger: Logger):
self.logger = logger
def create_user(self, name: str):
self.logger.log(f"ユーザー作成: {name}")
class UserServiceBuilder:
def __init__(self):
self._logger: Logger | None = None
def set_logger(self, logger: Logger) -> "UserServiceBuilder":
self._logger = logger
return self
def build(self) -> UserService:
if not self._logger:
raise ValueError("Logger is required")
return UserService(self._logger)
# 利用例
builder = UserServiceBuilder()
service = builder.set_logger(Logger()).build()
service.create_user("Hiroshi")
✅ 解説
このコードは Builder
パターン を使用して、複雑なオブジェクト(UserService
)の生成を段階的に構築する設計を実現している。
Builder
パターンは、オブジェクトの生成過程を分離し、柔軟かつ安全に構築できるようにするデザインパターン。
1. Builder パターンの概要
- Builder: オブジェクトの生成手順を定義するクラス
- このコードでは
UserServiceBuilder
が該当
- このコードでは
- Product:
Builder
によって生成されるオブジェクト- このコードでは
UserService
が該当
- このコードでは
- Client:
Builder
を使用してオブジェクトを構築するコード- このコードでは
UserServiceBuilder
を利用してUserService
を生成する部分が該当
- このコードでは
2. 主なクラスとその役割
Logger
- ログ出力を行うユーティリティクラス
UserService
の依存オブジェクトとして利用される
UserService
- 対象クラス(
Product
) - ユーザー作成機能を提供し、
Logger
を使用してログを出力
- 対象クラス(
UserServiceBuilder
- Builder クラス
setLogger
メソッドでLogger
を設定し、build
メソッドでUserService
を生成- 必須の依存関係(
Logger
)が設定されていない場合はエラーをスロー
- クライアントコード
UserServiceBuilder
を使用してUserService
を構築- 必要な依存関係を設定し、
build
メソッドでインスタンスを生成
3. UML クラス図
4. Builder パターンの利点
- 柔軟性: 必要な依存関係を段階的に設定可能
- 安全性: 必須の依存関係が設定されていない場合にエラーをスローすることで、不完全なオブジェクトの生成を防止
- 可読性: メソッドチェーンを使用することで、構築プロセスが直感的で可読性が高い
この設計は、複雑なオブジェクトの生成を柔軟かつ安全に行う。特に、依存関係が多いオブジェクトや、生成手順が複雑な場合に有効に機能する。