5

単純な動的 FS​​M を作成しました。Dynamicは、状態遷移が動的であり、 に示すように静的ではないことを意味しConcreteStateBます。

namespace FSM_Example
{
    using System;

    class Program
    {
        static void Main()
        {
            var context = new Context(new ConcreteStateA());
            context.Run();
            Console.Read();
        }
    }

    abstract class State
    {
        public abstract void Execute(Context context);
    }

    class ConcreteStateA : State
    {
        public override void Execute(Context context)
        {
            context.State = new ConcreteStateB();
        }
    }

    class ConcreteStateB : State
    {
        public override void Execute(Context context)
        {
            Console.Write("Input state: ");
            string input = Console.ReadLine();
            context.State = input == "e" ? null : new ConcreteStateA();
        }
    }

    class Context
    {
        private State _state;

        public Context(State state)
        {
            State = state;
        }

        public State State
        {
            get { return _state; }
            set
            {
                _state = value;
                Console.WriteLine("State: " + _state.GetType().Name);
            }
        }

        public void Run()
        {
            while (_state != null)
            {
                _state.Execute(this);
            }
        }
    }
}

これにより、 で説明されているステート マシンが実装されGoF305ます。

私は C# と .net が初めてなので: または のより具体的な機能を使用して、この目標を達成するためのより良いアプローチはあります.netC#?

4

2 に答える 2

2

適用できるアプローチはたくさんありますが、ほとんどの場合、達成する必要があるタスクによって異なります。

  1. 抽象クラスの代わりにインターフェイスを使用できます。C# では、複数のクラスを継承することはできないため、実現からこのオプションを使用しないことは常に良いことです。

    interface IState
    {
         void Handle(Context context);
    }
    
  2. ジェネリックを使用できるため、State パターンの基本インターフェイス/クラスを一度記述すれば、どこでも使用できます。

    abstract class IState<T>
    {
         void Handle(T context);
    }
    
  3. 次に行うことは、何を隠したいか、または隠したくないかによって異なります。たとえば、プロパティ State のセッターを非表示にして、dll の外部で誰も使用できないようにすることができるため、このプロパティのセッターを作成できますinternal

  4. 次のような状態変更に非同期を使用できます

    interface IState
    {
         Task HandleAsync(Context context);
    }
    
    class Context
    {
        // ...
    
        public async Task RunAsync()
        {
            while (_state != null)
            {
                await _state.HandleAsync(this);
            }
        }
    }
    
  5. 誰かがすでにRxで実装しているに違いない

于 2013-04-09T22:13:06.613 に答える