🧩 Strategy パターン
✅ 設計意図
- 状態ではなく、外部から差し替える「戦略」として振る舞いを扱う
- 状態遷移の管理は外部で実装される
✅ 適用理由
- 状態と振る舞いを完全に分離したい場合に有効
- 「振る舞いの切り替え」に集中したい場合はこちら
✅ 向いているシーン
- 状態管理そのものが不要で、ただ処理だけ差し替えたいとき
✅ コード例
- TypeScript
- PHP
- Python
// Strategy インターフェース
interface PublishStrategy {
publish(): void;
}
// 各戦略
class DraftStrategy implements PublishStrategy {
publish(): void {
console.log("レビュー依頼を送信");
}
}
class ReviewStrategy implements PublishStrategy {
publish(): void {
console.log("公開しました");
}
}
class PublishedStrategy implements PublishStrategy {
publish(): void {
console.log("すでに公開済みです");
}
}
// コンテキスト
class Document {
constructor(private strategy: PublishStrategy) {}
setStrategy(strategy: PublishStrategy): void {
this.strategy = strategy;
}
publish(): void {
this.strategy.publish();
}
}
// 利用例
const doc = new Document(new DraftStrategy());
doc.publish(); // → レビュー依頼
doc.setStrategy(new ReviewStrategy());
doc.publish(); // → 公開
doc.setStrategy(new PublishedStrategy());
doc.publish(); // → すでに公開済み
<?php
interface PublishStrategy {
public function publish(): void;
}
class DraftStrategy implements PublishStrategy {
public function publish(): void {
echo "レビュー依頼を送信\n";
}
}
class ReviewStrategy implements PublishStrategy {
public function publish(): void {
echo "公開しました\n";
}
}
class PublishedStrategy implements PublishStrategy {
public function publish(): void {
echo "すでに公開済みです\n";
}
}
class Document {
public function __construct(private PublishStrategy $strategy) {}
public function setStrategy(PublishStrategy $strategy): void {
$this->strategy = $strategy;
}
public function publish(): void {
$this->strategy->publish();
}
}
// 利用例
$doc = new Document(new DraftStrategy());
$doc->publish(); // → レビュー依頼
$doc->setStrategy(new ReviewStrategy());
$doc->publish(); // → 公開
$doc->setStrategy(new PublishedStrategy());
$doc->publish(); // → すでに公開済み
from abc import ABC, abstractmethod
class PublishStrategy(ABC):
@abstractmethod
def publish(self):
pass
class DraftStrategy(PublishStrategy):
def publish(self):
print("レビュー依頼を送信")
class ReviewStrategy(PublishStrategy):
def publish(self):
print("公開しました")
class PublishedStrategy(PublishStrategy):
def publish(self):
print("すでに公開済みです")
class Document:
def __init__(self, strategy: PublishStrategy):
self._strategy = strategy
def set_strategy(self, strategy: PublishStrategy):
self._strategy = strategy
def publish(self):
self._strategy.publish()
# 利用例
doc = Document(DraftStrategy())
doc.publish() # → レビュー依頼
doc.set_strategy(ReviewStrategy())
doc.publish() # → 公開
doc.set_strategy(PublishedStrategy())
doc.publish() # → すでに公開済み
✅ 解説
このコードは Strategy
パターン を使用して、ドキュメントの公開処理を戦略(PublishStrategy
)として分離し、
動的に切り替えられる設計を実現している。Strategy
パターンは、アルゴリズムや処理をクラスとして分離し、動的に切り替え可能にするデザインパターン。
1. Strategy パターンの概要
- Strategy: 共通のインターフェースを定義し、異なるアルゴリズムを統一的に扱う
- このコードでは
PublishStrategy
が該当
- このコードでは
- ConcreteStrategy:
Strategy
を実装し、具体的なアルゴリズムを提供する- このコードでは
DraftStrategy
,ReviewStrategy
,PublishedStrategy
が該当
- このコードでは
- Context:
Strategy
を利用するクラスで、具体的なアルゴリズムを動的に切り替える- このコードでは
Document
が該当
- このコードでは
2. 主なクラスとその役割
PublishStrategy
- 公開処理の共通インターフェース
publish(): void
メソッドを定義
DraftStrategy
,ReviewStrategy
,PublishedStrategy
PublishStrategy
を実装した具体的な戦略クラス- 各クラスで異なる公開処理を提供
DraftStrategy
: 「レビュー依頼を送信」ReviewStrategy
: 「公開しました」PublishedStrategy
: 「すでに公開済みです」
Document
Context
クラス- コンストラクタで
PublishStrategy
を受け取り、publish
メソッドで現在の戦略に応じた処理を実行 setStrategy
メソッドで戦略を動的に切り替え可能
3. UML クラス図
4. Strategy パターンの利点
- 柔軟性: 戦略を動的に切り替えることで、異なる処理を簡単に適用可能
- 単一責任の原則: 各戦略が独立したクラスに分離されており、保守性が高い
- 拡張性: 新しい戦略を追加する場合も、
PublishStrategy
を実装するだけで対応可能
この設計は、アルゴリズムや処理を柔軟に切り替える必要がある場面で非常に有効であり、コードの拡張性と保守性を向上させる。