State パターン

State パターン（、ステート・パターン）とは、プログラミングで用いられる デザインパターンの一種である。このパターンはオブジェクトの状態（state）を表現するために用いられる。ランタイムでそのタイプを部分的に変化させるオブジェクトを扱うクリーンな手段となる。
擬似コードによる例.
ドローソフトを例に取る。このプログラムは任意の時点においてさまざまなツールのうちの1つとして振る舞うマウスカーソルを持つ。複数のカーソルオブジェクトを切り替える代わりに、カーソルは現在使用されているツールを表す内部的な状態を保持する。（例えばマウスクリックの結果として）ツールに依存するメソッドが呼ばれると、メソッド呼び出しはカーソルの状態へと渡される。
各ツールは1つの状態に対応している。共有される抽象状態クラスはAbstractToolである。
 class AbstractTool is
 function moveTo(point) is
 input: the location "point" the mouse moved to
 "(this function must be implemented by subclasses)"
 function mouseDown(point) is
 input: the location "point" the mouse is at
 "(this function must be implemented by subclasses)"
 function mouseUp(point) is
 input: the location "point" the mouse is at
 "(this function must be implemented by subclasses)"
この定義により、各ツールはマウスカーソルの移動およびクリック／ドラッグの開始と終了を扱わなければならない。
その基底クラスを用い、単純なペンと範囲選択の各ツールを定義すると以下のようになる。
 subclass PenTool of AbstractTool is
 last_mouse_position := invalid
 mouse_button := up
 function moveTo(point) is
 input: the location "point" the mouse moved to
 if mouse_button = down
 "(draw a line from the "last_mouse_position" to "point")"
 last_mouse_position := point
 function mouseDown(point) is
 input: the location "point" the mouse is at
 mouse_button := down
 last_mouse_position := point
 function mouseUp(point) is
 input: the location "point" the mouse is at
 mouse_button := up
 
 subclass SelectionTool of AbstractTool is
 selection_start := invalid
 mouse_button := up
 function moveTo(point) is
 input: the location "point" the mouse moved to
 if mouse_button = down
 "(select the rectangle between "selection_start" and "point")"
 function mouseDown(point) is
 input: the location "point" the mouse is at
 mouse_button := down
 selection_start := point
 function mouseUp(point) is
 input: the location "point" the mouse is at
 mouse_button := up
この例では、コンテキストのためのクラスはCursorと呼ばれている。抽象状態クラス（この場合AbstractTool）で名付けられたメソッド群はコンテキストにおいても実装されている。コンテキストクラスではこれらのメソッドは、current_toolにより表される現在の状態の、対応するメソッドを呼び出す。
 class Cursor is
 current_tool := new PenTool
 function moveTo(point) is
 input: the location "point" the mouse moved to
 current_tool.moveTo(point)
 function mouseDown(point) is
 input: the location "point" the mouse is at
 current_tool.mouseDown(point)
 function mouseUp(point) is
 input: the location "point" the mouse is at
 current_tool.mouseUp(point)
 function usePenTool() is
 current_tool := new PenTool
 function useSelectionTool() is
 current_tool := new SelectionTool
Cursorオブジェクトが、適切なメソッド呼び出しをアクティブとなっているツールへと渡すことにより、異なる時点においてPenToolとSelectionToolのどちらとしてでも振舞えるのである。これがStateパターンの本質である。この場合では、PenCursorクラスとSelectCursorクラスを作ることで状態とオブジェクトを結合することも可能であり、単なる継承へと単純化できたであろうが、実践においては新しいツールが選択される毎に新しいオブジェクトへとコピーするにはコストがかかりすぎたりエレガントでなかったりするようなデータをCursorが保持していることもあるであろう。
Javaによる例.
以下は状態（State）のインタフェースと2つの実装である。状態メソッドはコンテキストオブジェクトへの参照を持ち、その状態を変えることができる。
interface State {
 void writeName(StateContext stateContext, String name);
class StateA implements State {
 public void writeName(StateContext stateContext, String name) {
 System.out.println(name.toLowerCase());
 // コンテキストをStateBに遷移する
 stateContext.setState(new StateB());
class StateB implements State {
 private int count = 0;
 public void writeName(StateContext stateContext, String name){ 
 System.out.println(name.toUpperCase()); 
 // StateBのwriteName()が2度呼び出された後にコンテキストをStateAに遷移する
 if (++count > 1) { 
 stateContext.setState(new StateA()); 
コンテキストクラスは、初期状態（この場合はStateA）でインスタンス生成したところの状態変数を持つ。そのメソッドでは、状態オブジェクトの対応するメソッドを使用する。
public class StateContext {
 private State myState;
 public StateContext() {
 setState(new StateA());
 // 通常は、Stateインタフェースを実装しているクラスによってのみ呼び出される
 public void setState(State newState) {
 this.myState = newState;
 public void writeName(String name) {
 this.myState.writeName(this, name);
用法は以下。
public class TestClientState {
 public static void main(String[] args) {
 StateContext sc = new StateContext();
 sc.writeName("Monday");
 sc.writeName("Tuesday");
 sc.writeName("Wednesday");
 sc.writeName("Thursday");
 sc.writeName("Saturday");
 sc.writeName("Sunday");
TestClientStateからのmain()の出力は次のようになるはずである。
monday
TUESDAY
WEDNESDAY
thursday
SATURDAY
SUNDAY