Skip to content

Instantly share code, notes, and snippets.

@gaevoy
Last active April 5, 2018 07:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gaevoy/fd6e8af47f466a970ce9deb70ca8605b to your computer and use it in GitHub Desktop.
Save gaevoy/fd6e8af47f466a970ce9deb70ca8605b to your computer and use it in GitHub Desktop.
StateMachineExample is simplistic example on how to implement state machine pattern without any framework
using System;
class StateOwner // This class must be persisted in database by ORM
{
private State _state;
public string StateType { get; set; }
public State State
{
get { return _state ?? (_state = State.Create(StateType, this)); }
set { _state = value; }
}
public int NumberOfAttempts { get; set; }
public string Captcha { get; set; }
}
abstract class State
{
protected StateOwner Owner { get; set; }
public virtual void Login(bool success) => InvalidOperation();
public virtual void InputCaptcha(string captcha) => InvalidOperation();
public virtual void Logout() => InvalidOperation();
protected virtual void OnStart() {}
protected void InvalidOperation() { throw new InvalidOperationException(); }
protected void Become(State next)
{
next.OnStart();
Owner.StateType = next.GetType().Name;
Owner.State = next;
}
public static State Create(string type, StateOwner owner)
{
switch (type)
{
case nameof(UserIsAuthorized): return new UserIsAuthorized(owner);
case nameof(UserInputsCaptcha): return new UserInputsCaptcha(owner);
case nameof(UserIsBlocked): return new UserIsBlocked(owner);
default: return new UserAtemptsToLogin(owner);
}
}
}
class UserAtemptsToLogin : State
{
public UserAtemptsToLogin(StateOwner owner)
{
Owner = owner;
}
protected override void OnStart()
{
Owner.NumberOfAttempts = 0;
}
public override void Login(bool success)
{
if (success)
Become(new UserIsAuthorized(Owner));
else
{
Owner.NumberOfAttempts++;
if (Owner.NumberOfAttempts > 10)
Become(new UserInputsCaptcha(Owner));
}
}
}
class UserIsAuthorized : State
{
public UserIsAuthorized(StateOwner owner)
{
Owner = owner;
}
public override void Logout()
{
Become(new UserAtemptsToLogin(Owner));
}
}
class UserInputsCaptcha : State
{
public UserInputsCaptcha(StateOwner owner)
{
Owner = owner;
}
protected override void OnStart()
{
Owner.Captcha = Guid.NewGuid().ToString();
}
public override void InputCaptcha(string captcha)
{
if (captcha == Owner.Captcha)
Become(new UserAtemptsToLogin(Owner));
else
Become(new UserIsBlocked(Owner));
}
}
class UserIsBlocked : State
{
public UserIsBlocked(StateOwner owner)
{
Owner = owner;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment