State Pattern
Contents
The same input can produce a different output, depending on the context/current state of the machine .
+Pressing "Coke" on a Vending Machine won'give a Coke un*ess it has money inside.flowchartDiagrams: enable: false * options: ""
sequenceDiagrams: enable: false options: ""
State Machine
A finite state machine has, at any given time, only one state.
The state changes only in response to some external input.
The change from one state to another is called a transition
The same input can produce a different output, depending on the context/current state of the machine.
i.e. Pressing "Coke" on a Vending Machine won't give a Coke unless it has money inside.
A basic state pattern
Consider the three inputs X, Y, Z, and the three states A, B, C
1 2 3 4 5 6 7 8 9 10 11 12 | myY() {
if (currentState == A) {
...
currentState = B;
} else if (currentState == B) {
...
currentState = C;
} else if (currentState == C) {
...
currentState = A;
}
} |
The same state pattern, with switch
1 2 3 4 5 6 7 8 9 10 11 12 | myY() {
switch (currentState) {
case A:
...
currentState = B;
case B:
...
currentState = C;
case C:
...
currentState = A;
} |
Issues
This is bad! Each new input or state will require the modification of all relevant if/else if / switch statements.
Solution
Instead, for each given state we could create a class that implements a common interface.
| |
Setting the state
In order to update the next state, we will have to pass in a way for the state to change.
Ideas
- Pass
thisinto all methods - Pass
this(context) in the state constructor- Create a
setContextmethod in the context, which the states can call
- Create a
- Pass an update callback function
this.state.myFunction(this.changeState);
- The return type of the values could be the next state
this.state = this.state.myFunction();
Best Method: Pass the context into the state class through the constructor. It is also a good idea to create the states during the initialisation of the context
