Задачи для начинающих
Начали мы с самой простой функции, но как оказалось, что в данной реализации дополнительную кнопку просто негде опрашивать. Извратиться конечно можно, но извращения нам ни к чему.
Так что функцию Delay /Задержка/ нужно как то убрать. Нужно ее просто преобразовать во что то, что не стоит тупо на месте. Можно просто проверять сколько прошло времени, но тогда потеряется последовательность состояний.
Какой выход? Увы только усложнять.
Давайте еще раз глянем на нашу функцию, что там можно увидеть?
Видим 4 состояния которые связаны между собой. Каждой состояние имеет определенный паттерн: инициализация при входе, задержка, некая работа перед выходом из состояния.
Так как классы мы уже начали изучать, то сразу виден некий базовый объект и наследуемые от него объекты которые будут определять инициализацию при входе в состояние и работу перед выходом. (Хотя в данном случае эта работа одинаковая для всех состояний)
internal class State { private readonly int _durationMs; private State _next; private int _startTime; public State(int durationMs) { _durationMs = durationMs; } public virtual void DoStateStep() { // do nothing here } public virtual void EnterState() { _startTime = Environment.TickCount; } public virtual void ExitState() { // do nothing here } public bool IsStateFinished() { return Environment.TickCount - _startTime >= _durationMs ; } public int DurationMs { get { return _durationMs; } } public State Next { get { return _next; } set { _next = value; } } }
Для сокращения места приведем только одно состояние, так как остальные состояния, будут отличаться всего одной функцией EnterState(), код которых берется из состояний 2,3,4
internal class AutoRedState : State { private readonly CombinedTrafficLight _trafficLight; public AutoRedState(CombinedTrafficLight trafficLight, int durationMs, State next = null) : base(durationMs, next) { _trafficLight = trafficLight; } public override void EnterState() { base.EnterState(); _trafficLight.DisableAutoTraffic(); _trafficLight.EnablePedestrianTraffic(); } public override void ExitState() { base.ExitState(); Program.TraceState(_trafficLight); } }
Еще будет интересно знать как выглядит основная функция.
private static void Main() { CombinedTrafficLight trafficLight = new CombinedTrafficLight(); InitTraceState(); //инициализация состояний ButtonSimulator button = new ButtonSimulator(); State redState = new AutoRedState(trafficLight, RedLightTimeMs); State yellowStateAfterRed = new AutoYellowAfterRedState(trafficLight, YellowLightTimeMs); State greenState = new AutoGreenState(trafficLight, GreenLightTimeMs, button); State yellowStateAfterGreen = new AutoYellowAfterGreenState(trafficLight, YellowLightTimeMs); redState.Next = yellowStateAfterRed; yellowStateAfterRed.Next = greenState; greenState.Next = yellowStateAfterGreen; yellowStateAfterGreen.Next = redState; // цикл перехода между состояниями State currentState = redState; currentState.EnterState(); while (true) { button.CheckButtonState(); currentState.DoStateStep(); if (currentState.IsStateFinished()) { currentState.ExitState(); button.ClearPressedState(); currentState = currentState.Next; if (currentState == null) { break; } currentState.EnterState(); } Thread.Sleep(100); } }
Вроде бы кода много добавили, но более запутанным, он по идее не стал. По крайней мере если надо изменить состояние - изменяем класс конкретного состояния.
Нужно добавить новое состояние, тоже происходит без проблем, не нужно исправлять много разных частей.