🧩 Iterator パターン
✅ 設計意図
- 複雑な処理に含まれる 繰り返し処理(ループ)部分を分離 し、汎用的なインターフェースでアクセス
- 処理の 「流れ」ではなく「走査ロジック」 を抽象化し、再利用性と可読性を向上
✅ 適用理由
- Facade や Proxy でまとめられている処理の中に、コレクション操作や繰り返しが含まれている場合
- 同じようなループ処理が各所にコピペされている → 一元化できる
✅ 向いているシーン
- ユーザー一覧、ログのページ送り、レポート生成、ファイル構造など、反復的な処理を含む複雑処理
✅ コード例
- TypeScript
- PHP
- Python
interface Step {
execute(context: Record<string, any>): void;
}
class AuthStep implements Step {
execute(context: Record<string, any>): void {
console.log(`ユーザー認証: ${context.userId}`);
context.authenticated = true;
}
}
class LoadProfileStep implements Step {
execute(context: Record<string, any>): void {
if (!context.authenticated) throw new Error("未認証");
console.log(`プロフィール取得: ${context.userId}`);
context.profile = { name: "Hiroshi", id: context.userId };
}
}
class AuditStep implements Step {
execute(context: Record<string, any>): void {
console.log("[監査ログ] プロフィール表示");
}
}
class UserProfileFlow {
private steps: Step[] = [];
constructor() {
this.steps = [new AuthStep(), new LoadProfileStep(), new AuditStep()];
}
execute(userId: string) {
const context: Record<string, any> = { userId };
for (const step of this.steps) {
step.execute(context);
}
console.log(context.profile);
}
}
// 利用例
const flow = new UserProfileFlow();
flow.execute("user-123");
<?php
interface Step {
public function execute(array &$context): void;
}
class AuthStep implements Step {
public function execute(array &$context): void {
echo "ユーザー認証: {$context['userId']}\n";
$context['authenticated'] = true;
}
}
class LoadProfileStep implements Step {
public function execute(array &$context): void {
if (!($context['authenticated'] ?? false)) {
throw new Exception("未認証");
}
echo "プロフィール取得: {$context['userId']}\n";
$context['profile'] = ['name' => 'Hiroshi', 'id' => $context['userId']];
}
}
class AuditStep implements Step {
public function execute(array &$context): void {
echo "[監査ログ] プロフィール表示\n";
}
}
class UserProfileFlow {
private array $steps;
public function __construct() {
$this->steps = [new AuthStep(), new LoadProfileStep(), new AuditStep()];
}
public function execute(string $userId): void {
$context = ['userId' => $userId];
foreach ($this->steps as $step) {
$step->execute($context);
}
print_r($context['profile']);
}
}
// 利用例
$flow = new UserProfileFlow();
$flow->execute("user-123");
from abc import ABC, abstractmethod
class Step(ABC):
@abstractmethod
def execute(self, context: dict):
pass
class AuthStep(Step):
def execute(self, context: dict):
print(f"ユーザー認証: {context['user_id']}")
context['authenticated'] = True
class LoadProfileStep(Step):
def execute(self, context: dict):
if not context.get('authenticated'):
raise Exception("未認証")
print(f"プロフィール取得: {context['user_id']}")
context['profile'] = {"name": "Hiroshi", "id": context['user_id']}
class AuditStep(Step):
def execute(self, context: dict):
print("[監査ログ] プロフィール表示")
class UserProfileFlow:
def __init__(self):
self.steps: list[Step] = [AuthStep(), LoadProfileStep(), AuditStep()]
def execute(self, user_id: str):
context = {"user_id": user_id}
for step in self.steps:
step.execute(context)
print(context["profile"])
# 利用例
flow = UserProfileFlow()
flow.execute("user-123")
✅ 解説
このコードは Iterator
パターン を使用して、UserProfileFlow
内で一連の処理(Step)を順番に実行する設計を実現している。
Iterator
パターンは、コレクション内の要素を順番にアクセスする方法を提供するデザインパターン。
このコードでは、Step
のリストを順に処理することで、ユーザー認証、プロフィール取得、監査ログ記録を実現している。
1. Iterator パターンの概要
- Aggregate: コレクションを保持し、要素にアクセスするためのインターフェースを提供
- このコードでは
UserProfileFlow
が該当
- このコードでは
- Iterator: コレクション内の要素を順番にアクセスするためのインターフェース
- このコードでは
for...of
ループがその役割を果たしている
- このコードでは
- ConcreteElement: コレクション内の個々の要素
- このコードでは
Step
を実装したAuthStep
,LoadProfileStep
,AuditStep
が該当
- このコードでは
2. 主なクラスとその役割
Step
- 各処理ステップの共通インターフェース
execute(context: Record<string, any>): void
メソッドを定義
AuthStep
,LoadProfileStep
,AuditStep
Step
を実装した具体的なステップクラス- 各クラスで異なる処理を実行
AuthStep
: ユーザー認証を実行LoadProfileStep
: 認証済みのユーザーのプロフィールを取得AuditStep
: 監査ログを記録
UserProfileFlow
- コレクション(
Aggregate
)を保持するクラス steps
配列にStep
を格納し、execute
メソッドで順番に処理を実行
- コレクション(
3. UML クラス図
4. Iterator パターンの利点
- 順序の明確化: コレクション内の要素を順番に処理するロジックを簡潔に記述可能
- 拡張性: 新しいステップを追加する場合も、
Step
を実装してsteps
配列に追加するだけで対応可能 - 柔軟性: 各ステップが独立しているため、処理の変更や再利用が容易
この設計は、一連の処理を順番に実行する必要がある場面で非常に有効であり、コードの拡張性と保守性を向上させる。