Last active
April 5, 2018 07:59
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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