Human above all, with pathos, weaknesses and grumpy at times. Speak for myself; think out loud. Direct, seemingly hard faced. Urged to fix things. Am fortunate.
State Machine Don't Abuse The If
This is possibly the most hideous usage of if since not only makes your code hard to follow but also you have to keep track of your object’s state since execution flow changes every time. All in your head that is.
In addition it’s hard to figure out how the object behaves at each state as well as how the transitions between them happen. Because of that it makes it a pain to debug and to extend.
What you need to do instead is think of all the possible states your object can have and create an implementation for each. This way each state effectively encapsulates only what’s responsible for. Notice how each state also sets the next valid state of your object depending on what method you called, making your object look as if it’s a different one. For that you need to have a reference to your actual class.
As a result each state mirrors your class interface. If a method isn’t valid for a particular state make sure that you throw an IllegalStateException. In that case you’ll know early that something unexpected happened, which is most likely an error on how you wired your code.
Effectively you end up with state being the only non final field in your class.
Create an interface with all the methods related to the object’s state
Create an implementation for each state
Have a single field in your actual class holding the current state
Delegate each call to the current state
As to how to identify the state machine itself, it really goes back to the beginning
Kudos to Ioannis Cherouvim who is a Java developer and regularly writes blogs posts about using Java effectively. Trying to convince him to join @qnoid and hopefully write some more here as well. If you have an invite to spare please let me know :)
The source code is available on github as stated previously. Feel free to fork it and add a LoggedOut state which allows the user to logout and set the appropriate state