StateパターンおよびContextのインターフェイス 続き
Contextをインターフェイスにする例。
時間経過と共に色が最大3段階変化する電灯をStateパターンで実装してみる。
電灯のコンテキストのインターフェイスクラス
class LightState; class LightContext { public: virtual ~LightContext() {} // 状態を遷移させる virtual LightState* ChangeState( LightState* nextState ) = 0; // 時間経過を行う virtual void PassTime( time_t timePassed ) = 0; // 色を表示する virtual void PrintColor() = 0; };
電灯の状態のインターフェイスクラス
class LightContext; class LightState { public: virtual ~LightState() {} // 時間経過を行う virtual void PassTime( LightContext* context, time_t timePassed ) = 0; // 色を出力する virtual void PrintColor() = 0; };
一つ目の電灯の状態
class FirstLightState : public LightState { private: time_t m_timePassed; static FirstLightState* instance; FirstLightState(); public: ~FirstLightState(); static FirstLightState* Instance(); // 2秒経過したら次の状態に遷移する void PassTime( LightContext* context, time_t timePassed ); // 赤を表示する void PrintColor(); };
2つ目の電灯の状態
class SecondLightState : public LightState { private: time_t m_timePassed; static SecondLightState* instance; SecondLightState(); public: ~SecondLightState(); static SecondLightState* Instance(); // 3秒経過したら次の状態に遷移する void PassTime( LightContext* context, time_t timePassed ); // 黄と表示する void PrintColor(); };
3つ目の電灯の状態
class ThirdLightState : public LightState { private: time_t m_timePassed; static ThirdLightState* instance; ThirdLightState(); public: ~ThirdLightState(); static ThirdLightState* Instance(); // 何もしない void PassTime( LightContext* context, time_t timePassed ); // 青と表示する void PrintColor();
3つの状態をとる電灯
class TriStateLightContext : public LightContext { private: LightState* m_state; public: TriStateLightContext(); ~TriStateLightContext(); // 状態を指定された状態へ遷移させる LightState* ChangeState( LightState* nextState ); // 時間を経過させる void PassTime( time_t timePassed ); // 現在の状態の色を表示する void PrintColor(); };
2つの状態をとる電灯
class TwoStateLightContext : public LightContext { private: LightState* m_state; public: TwoStateLightContext(); ~TwoStateLightContext(); // 状態を指定された状態のうちSecondLightState以外は指定された状態へ // SecondLightStateの場合はThirdLightStateへ遷移させる LightState* ChangeState( LightState* nextState ); // 時間を経過させる void PassTime( time_t timePassed ); // 現在の状態の色を表示する void PrintColor(); };
ここでは電灯の状態として3つの状態があるが、
電灯によっては2状態のみ取りうるものと、3状態取りうるものとを
別々のクラスとして実装している。
場合によっては、例外的にあるクラスでのみ
状態遷移シーケンスを変化させたい場合などがあり、
そのための条件をStateに含めずにContext側に持たせるようなケースが考えられる。
(あまり状態を増やしすぎると状態数が爆発するのでトレードオフ)
このような場合、Contextをインターフェイスにして実装を変化させることで
例外的な状態遷移を行うことができる。
ただし、TwoStateLightContextクラスはSecondLightStateクラスや
ThirdLightStateクラスのことを知らなければいけなくなってしまう。
この辺はもう少しうまい例がありそうな気がするが、
今はちょっと思い浮かばない orz