I notice a difference with state Pattern. its more handy when using it for UI. lets say i wanted to lock the state. in the state Pattern context i could create a boolean and prevent states from changing further.
here is a Kotlin example:
inner class StateContext : State {
private var stateContext: State? = null
private var lockState: Boolean = false
fun isLockState(): Boolean {
return lockState
}
fun setLockState(lockState: Boolean): StateContext {
this.lockState = lockState//no further actions allowed. useful if you need to permenatley lock out the user from changing state.
return this
}
fun getState(): State? {
return this.stateContext
}
fun setState(state: State): StateContext {
if (!lockState) this.stateContext = state
return this
}
override fun doAction() {
this.stateContext?.doAction()
}
}
with state machine im not sure how that would be done easily.
i really like state machine when im worried about just the state (saving enum of current state for example ) , not the actual implementation detail (changing UI buttons color , for example) . the one thing about state machine thats good, is that you can have a central place to log state changes. i saw this library for kotlin by tinder which looks interesting. but i do personally think you could change them all to do what you want, just more cleaner one way vs another.
what is a stateMachine then ? the stateMachine cares more about "what is the next state", its highlighting transition of the states rather then its detail. It maintains a flow. Usually you create it using enums. this article helps clear it up ( and references below are taken from there to help clear up the differences) but essentially this would be a state machine:
public enum LeaveRequestState {
Submitted {
@Override
public LeaveRequestState nextState() {
return Escalated;
}
@Override
public String responsiblePerson() {
return "Employee";
}
},
Escalated {
@Override
public LeaveRequestState nextState() {
return Approved;
}
@Override
public String responsiblePerson() {
return "Team Leader";
}
},
Approved {
@Override
public LeaveRequestState nextState() {
return this;
}
@Override
public String responsiblePerson() {
return "Department Manager";
}
};
public abstract LeaveRequestState nextState();
public abstract String responsiblePerson();
}
now you know what the next transition state is for each event. So state machine CARES greatly for transitions over actually implementation of the state:
LeaveRequestState state = LeaveRequestState.Submitted;
state = state.nextState();
assertEquals(LeaveRequestState.Escalated, state);
state = state.nextState();
assertEquals(LeaveRequestState.Approved, state);
state = state.nextState();
assertEquals(LeaveRequestState.Approved, state);