Autumn SALE
State

State を C# で

State 振る舞いに関するデザインパターンの一つで オブジェクトの内部状態が変化した時にその振る舞いを変更することを可能とします

このパターンは 状態に関連した振る舞いを個別の状態のクラスへ抽出し 元のオブジェクトが作業を自分で行わず これらのクラスのインスタンスに委任することを強制します

複雑度

人気度

使用例 C# では State パターンは 膨大な数の switch 文に基づく状態機械をオブジェクトに変換する時によく使われます

見つけ方 オブジェクトが その外的に制御される状態によって振る舞いを変えるようなメソッドを持っていたら State パターンを識別できます

概念的な例

この例は State デザインパターンの構造を説明するためのものです 以下の質問に答えることを目的としています

  • どういうクラスからできているか
  • それぞれのクラスの役割は
  • パターンの要素同士はどう関係しているのか

Program.cs: 概念的な例

using System;

namespace RefactoringGuru.DesignPatterns.State.Conceptual
{
    // The Context defines the interface of interest to clients. It also
    // maintains a reference to an instance of a State subclass, which
    // represents the current state of the Context.
    class Context
    {
        // A reference to the current state of the Context.
        private State _state = null;

        public Context(State state)
        {
            this.TransitionTo(state);
        }

        // The Context allows changing the State object at runtime.
        public void TransitionTo(State state)
        {
            Console.WriteLine($"Context: Transition to {state.GetType().Name}.");
            this._state = state;
            this._state.SetContext(this);
        }

        // The Context delegates part of its behavior to the current State
        // object.
        public void Request1()
        {
            this._state.Handle1();
        }

        public void Request2()
        {
            this._state.Handle2();
        }
    }
    
    // The base State class declares methods that all Concrete State should
    // implement and also provides a backreference to the Context object,
    // associated with the State. This backreference can be used by States to
    // transition the Context to another State.
    abstract class State
    {
        protected Context _context;

        public void SetContext(Context context)
        {
            this._context = context;
        }

        public abstract void Handle1();

        public abstract void Handle2();
    }

    // Concrete States implement various behaviors, associated with a state of
    // the Context.
    class ConcreteStateA : State
    {
        public override void Handle1()
        {
            Console.WriteLine("ConcreteStateA handles request1.");
            Console.WriteLine("ConcreteStateA wants to change the state of the context.");
            this._context.TransitionTo(new ConcreteStateB());
        }

        public override void Handle2()
        {
            Console.WriteLine("ConcreteStateA handles request2.");
        }
    }

    class ConcreteStateB : State
    {
        public override void Handle1()
        {
            Console.Write("ConcreteStateB handles request1.");
        }

        public override void Handle2()
        {
            Console.WriteLine("ConcreteStateB handles request2.");
            Console.WriteLine("ConcreteStateB wants to change the state of the context.");
            this._context.TransitionTo(new ConcreteStateA());
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // The client code.
            var context = new Context(new ConcreteStateA());
            context.Request1();
            context.Request2();
        }
    }
}

Output.txt: 実行結果

Context: Transition to ConcreteStateA.
ConcreteStateA handles request1.
ConcreteStateA wants to change the state of the context.
Context: Transition to ConcreteStateB.
ConcreteStateB handles request2.
ConcreteStateB wants to change the state of the context.
Context: Transition to ConcreteStateA.

他言語での State

State を C++ で State を Go で State を Java で State を PHP で State を Python で State を Ruby で State を Rust で State を Swift で State を TypeScript で