Update:
State pattern might a wrong way to solve this. Hence, any other pattern is welcome. Basically I'm looking for a way to have guard conditions for each state yet having a clean and maintainable code. How would front-end side routing systems like, emberjs, ui-router and react-router implement guard conditions
to avoid entering a specific state if the condition is not met?
I want to implement a finite state machine by using State Pattern but I can't wrap my head around it. In short it's like:
If error -> error state
If A && B && C -> second state
If only A -> first state
At any state, on error, we go to error state. inputs (events) A, B and C might arrive at any order but if they all pass we go to 2nd state. If only input A applies, then we go to 1st state.
The following state diagram is taken from Martin Fowler's Domain Specific Language book.
In the description he says:
Miss Grant, has a secret compartment in her bedroom that is normally locked and concealed. To open it, she has to close the door, then open the second drawer in her chest and turn her bedside light on in either order. Once these are done, the secret panel is unlocked for her to open.
I emphasize, that turning light
and opening 2nd drawer
can happen in either order. Same as A, B and C.
Based on @SQLPolice comment and the book, I have drawn this:
But the problem is, I might have (A && B && C && D && D && E). In that case it's gonna be cumbersome to have all of the combination interim states.
Example. The State pattern allows an object to change its behavior when its internal state changes. This pattern can be observed in a vending machine. Vending machines have states based on the inventory, amount of currency deposited, the ability to make change, the item selected, etc.
The state pattern is used in computer programming to encapsulate varying behavior for the same object, based on its internal state. This can be a cleaner way for an object to change its behavior at runtime without resorting to conditional statements and thus improve maintainability.
The State pattern minimizes conditional complexity, eliminating the need for if and switch statements in objects that have different behavior requirements unique to different state transitions.
State Pattern defines the “what” and “when” part of an Object. Example: What can an object when it's in a certain state. Strategy pattern defines the “How” part of an Object. Example: How a Sorting object sorts data.
You can use some form of lexical analysis for this. I would approach this by limiting the ability to transition from a state unless the constraints placed on the edge between the two states are met. I wrote an FSM in PHP recently for the Laravel framework that has an example such as this where various constraints are all required to be true before a transition can occur. It uses pseudo states or handles within a state to toggle a flag stating that a process has completed. Only when all flags are set to true can the state transition.
Using the FSM package I wrote for laravel, an example FSM setup would look something like this.
Each state would (either onEnter) or via a pseudo state set it's constraint flag on the FSM OR State to true.
This would also trigger a checkReady()
that would trigger the transition or keep the current state based on the constraint flags.
Adding in new constraints is a case of adding them to an array of constraints within the state or the containing FSM and building a method to allow the constraint to be removed when a task is performed.
When you are looking at multiple states, with each state forming a requirement on the constraints. A sample state would look something like this.
When you are looking at a single state with pseudo states / handlers. The state would look something like this, where it's logic is contained.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With