Dave Elliott Ответов: 1

Построение государственной машины


Я смотрю на создание государственной машины для проекта. В проекте будет много алгоритмов, каждый из которых имеет в себе государственную машину. Возвращение перечисления для следующего состояния загрязнило бы перечисление базового класса, поэтому я не очень рад этому.

Ниже приведен рабочий код, который я придумал. Не без ума от возвращаемого типа объекта, но на самом деле не вижу способа обойти его.

У кого-нибудь есть какие-нибудь мысли?

Что я уже пробовал:

using System;

namespace StateMachine
{
	/// 
	public class StateMachine2BaseClass
	{
		protected void RunAlgorithm(Func<object> nextState)
		{
			while (nextState != null)
			{
				var currentState = nextState;
				nextState = (Func<object>)currentState();
			}
		}

		protected Func<object> End()
		{
			return null;
		}
	}

	/// 
	public class StateMachine2 : StateMachine2BaseClass
	{
		private int count;

		public void Run()
		{
			RunAlgorithm(Start);
		}

		private Func<object> Start()
		{
			Console.WriteLine("Start");
			return Step_1;
		}

		private Func<object> Step_1()
		{
			if (++count > 5)
				return Step_2;

			Console.WriteLine("Step 1");

			return Step_1;
		}

		private Func<object> Step_2()
		{
			Console.WriteLine("Step 2");
			return End;
		}
	}
}

F-ES Sitecore

Вместо того чтобы использовать функции для определения своего состояния, вы лучше используете классы. Это может означать больше кодирования, но оно будет более гибким и безопасным для ввода.

http://www.codeproject.com/Articles/43356/A-Simple-State-Machine

Если вы загуглите "c# state machine", то найдете и другие примеры.

1 Ответов

Рейтинг:
0

OriginalGriff

Как предполагает F-ES Sitecore, классовый подход будет работать лучше.
Определите абстрактный класс состояний, который объявляет абстрактный метод DoWork, принимая в качестве параметра класс "machine info", описывающий информацию, с которой будут работать состояния, если таковые имеются, и возвращающий экземпляр состояния.

Затем для каждого состояния, которое вам нужно, определите новый класс, производный от класса State, и реализуйте метод DoWork для каждого.

Все, что вам нужно сделать, это:

protected void RunAlgorithm(Func<object> nextState)
    {
    State currentState = new FirstState();
    while (currentState != null)
        {
        currentState = currentState.DoWork(machineInfo);
        }
    }
Система сама разберется, какой метод DoWork ей нужно вызывать каждый раз.