Stateパターンとは | GoFデザインパターン

記事内に広告が含まれています。

Stateパターンは、オブジェクトの状態によってその振る舞いを変えるデザインパターンです。

このパターンは、GoF(Gang of Four)によって提唱された23のデザインパターンの一つであり、状態が変わるたびに異なる処理を実行する必要がある場合に有効です。

Stateパターンとは

Stateパターンの概要

Stateパターンは、オブジェクトの状態をオブジェクト自身が管理し、その状態に応じて異なる動作を行うことができるようにします。

たとえば、電源オン・オフ状態やユーザーのログイン状態など、状態に応じた処理が必要な場面で活躍します。

これにより、if文やswitch文での複雑な条件分岐を減らし、コードをシンプルかつ拡張性の高いものにします。

Stateパターンの使い方

Stateパターンを使うことで、オブジェクトの状態管理が容易になり、コードのメンテナンス性が向上します。

また、新しい状態を追加する際にも既存のコードに手を加える必要が少なく、拡張が容易です。

Stateパターンの実装例

Stateパターンの実装は、状態ごとにクラスを定義し、それらのクラスを切り替えることで動作を変えるアプローチが一般的です。

次のサンプルコードでは、Java、C++、C#、VB.NETの実装例を示します。

Stateパターン実装サンプル

以下にStateパターンのJava、C++、C#、VB.NETでの実装サンプルを示します。

それぞれのコードにはコメントを付加し、動作の流れを解説します。

Javaでの実装例


// Stateインターフェース
interface State {
    void doAction(Context context);
}

// 具体的な状態クラス
class StartState implements State {
    public void doAction(Context context) {
        System.out.println("Player is in start state");
        context.setState(this);
    }

    public String toString(){
        return "Start State";
    }
}

class StopState implements State {
    public void doAction(Context context) {
        System.out.println("Player is in stop state");
        context.setState(this);
    }

    public String toString(){
        return "Stop State";
    }
}

// Contextクラス
class Context {
    private State state;

    public Context(){
        state = null;
    }

    public void setState(State state){
        this.state = state;
    }

    public State getState(){
        return state;
    }
}

// メインクラス
public class StatePatternDemo {
    public static void main(String[] args) {
        Context context = new Context();

        StartState startState = new StartState();
        startState.doAction(context);

        System.out.println(context.getState().toString());

        StopState stopState = new StopState();
        stopState.doAction(context);

        System.out.println(context.getState().toString());
    }
}

C++での実装例


#include 
using namespace std;

class Context;

// Stateクラス
class State {
public:
    virtual void doAction(Context* context) = 0;
};

// 具体的な状態クラス
class StartState : public State {
public:
    void doAction(Context* context) override {
        cout << "Player is in start state" << endl;
        context->setState(this);
    }

    string toString() {
        return "Start State";
    }
};

class StopState : public State {
public:
    void doAction(Context* context) override {
        cout << "Player is in stop state" << endl;
        context->setState(this);
    }

    string toString() {
        return "Stop State";
    }
};

// Contextクラス
class Context {
private:
    State* state;

public:
    Context() : state(nullptr) {}

    void setState(State* state) {
        this->state = state;
    }

    State* getState() {
        return state;
    }
};

// メイン関数
int main() {
    Context context;

    StartState startState;
    startState.doAction(&context);
    cout << context.getState()->toString() << endl;

    StopState stopState;
    stopState.doAction(&context);
    cout << context.getState()->toString() << endl;

    return 0;
}

C#での実装例


// Stateインターフェース
public interface State {
    void DoAction(Context context);
}

// 具体的な状態クラス
public class StartState : State {
    public void DoAction(Context context) {
        Console.WriteLine("Player is in start state");
        context.SetState(this);
    }

    public override string ToString() {
        return "Start State";
    }
}

public class StopState : State {
    public void DoAction(Context context) {
        Console.WriteLine("Player is in stop state");
        context.SetState(this);
    }

    public override string ToString() {
        return "Stop State";
    }
}

// Contextクラス
public class Context {
    private State _state;

    public void SetState(State state) {
        _state = state;
    }

    public State GetState() {
        return _state;
    }
}

// メインクラス
class Program {
    static void Main(string[] args) {
        Context context = new Context();

        StartState startState = new StartState();
        startState.DoAction(context);

        Console.WriteLine(context.GetState().ToString());

        StopState stopState = new StopState();
        stopState.DoAction(context);

        Console.WriteLine(context.GetState().ToString());
    }
}

VB.NETでの実装例


' Stateインターフェース
Public Interface State
    Sub DoAction(ByVal context As Context)
End Interface

' 具体的な状態クラス
Public Class StartState
    Implements State
    Public Sub DoAction(ByVal context As Context) Implements State.DoAction
        Console.WriteLine("Player is in start state")
        context.SetState(Me)
    End Sub

    Public Overrides Function ToString() As String
        Return "Start State"
    End Function
End Class

Public Class StopState
    Implements State
    Public Sub DoAction(ByVal context As Context) Implements State.DoAction
        Console.WriteLine("Player is in stop state")
        context.SetState(Me)
    End Sub

    Public Overrides Function ToString() As String
        Return "Stop State"
    End Function
End Class

' Contextクラス
Public Class Context
    Private state As State

    Public Sub SetState(ByVal state As State)
        Me.state = state
    End Sub

    Public Function GetState() As State
        Return state
    End Function
End Class

' メイン関数
Module Module1
    Sub Main()
        Dim context As New Context()

        Dim startState As New StartState()
        startState.DoAction(context)

        Console.WriteLine(context.GetState().ToString())

        Dim stopState As New StopState()
        stopState.DoAction(context)

        Console.WriteLine(context.GetState().ToString())
    End Sub
End Module

まとめ

Stateパターンは、オブジェクトの状態ごとに異なる振る舞いを管理するのに適したデザインパターンです。

このパターンを利用することで、複雑な条件分岐を減らし、コードの可読性と拡張性が向上します。

Java、C++、C#、VB.NETといった多くのプログラミング言語で実装可能であり、状態に応じた処理が必要なシステム開発に役立つでしょう。

オブジェクト指向プログラミングにおけるGoFの23のデザインパターン
デザインパターンは、ソフトウェア設計の問題を効果的に解決するための再利用可能な解決策です。本記事では、GoF(Gang ...
タイトルとURLをコピーしました