🔥

デザインパターンを学ぶ #17 ステート(State)

に公開

1. はじめに

今回は State(ステート)パターン
目的は、オブジェクトの状態に応じて振る舞いを切り替える仕組みを作ることです。

典型的な用途は ゲームのキャラクター状態・会員ランク・ワークフロー管理など、状態に応じて処理を変える場面です。

2. Stateとは?

ステートパターンでは、状態をクラスとして表現し、コンテキストがその状態に処理を委譲します。
条件分岐を並べる代わりに、状態ごとにクラスを分けて整理します。

登場役は以下の通りです:

  • Context … 状態を持つ本体
  • State … 状態の共通インターフェース
  • ConcreteState … 具体的な状態クラス

3. 実装イメージ(PHP)

<?php

// State インターフェース
interface State {
    public function handle(): void;
}

// 具体的な状態
class GuestState implements State {
    public function handle(): void {
        echo "ゲスト:登録してください\n";
    }
}

class MemberState implements State {
    public function handle(): void {
        echo "会員:通常サービスを利用できます\n";
    }
}

class PremiumState implements State {
    public function handle(): void {
        echo "プレミアム会員:特典を利用できます\n";
    }
}

// Context 本体
class UserContext {
    private State $state;

    public function __construct(State $state) {
        $this->state = $state;
    }

    public function setState(State $state): void {
        $this->state = $state;
    }

    public function request(): void {
        $this->state->handle();
    }
}

// --- 実行例 ---
$context = new UserContext(new GuestState());
$context->request(); // ゲスト

$context->setState(new MemberState());
$context->request(); // 会員

$context->setState(new PremiumState());
$context->request(); // プレミアム会員

4. メリット・デメリット

メリット

  • 状態ごとにクラスを分けて整理できる
  • 条件分岐を避けられる
  • 状態追加が容易

デメリット

  • クラス数が増える
  • シンプルな処理では冗長になる

5. 使いどころ

  • ゲームの状態管理(歩く・攻撃・死亡など)
  • 会員ランク(ゲスト・会員・プレミアムなど)
  • ワークフローの進行管理(申請中・承認済み・却下など)

状態による振る舞いを明確に分けたいとき、Stateパターンが有効です。

Discussion