Object-Oriented Patterns: A Simplified Look at State Patterns in Java
source link: https://www.tuicool.com/articles/hit/aAfiIjF
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
There are tons of articles and videos about using object-oriented patterns. If you cannot find a truly good example that resonates with your pre-existing understanding of Java, it becomes a little hard to understand it. When I was biking with my 8-year-old son, I was always reminding him to gear down when he is biking uphill and to gear up when we are going flat or downhill. This gearing is a great example of how to use the State design pattern. For this tutorial, I will demonstrate the State design pattern through a biking example. I hope it will resonate with your learning style and be easily remembered for future reference.
First, I need to have a bike class. It should be pretty simple:
public class Bike { GearState gearState; public Bike(){ gearState = new FirstGear(this); } public void gearUp(){ gearState.gearUp(); } public void gearDown(){ gearState.gearDown(); } }
I kept the Bike
class as simple as possible. The Bike
class above is implemented using the State pattern. It could have been implemented with all of the state-related gear code inside, as long as you are able to use many "if" or "switch" conditions. The latter would be hard to maintain if you have many states. If you have a few states to maintain, the State pattern would complicate your design.
As you see in the code above, we have GearState
, which is nothing but an abstract class as you will see the full code below. The bike could extend from GearState
, but this is not a "IS A" relationship. This is why I did not extend, because, in the State Pattern, extending the State interface is not a common practice.
public abstract class GearState { Bike bike; GearState(Bike bike){ this.bike = bike; } public abstract void gearUp(); public abstract void gearDown(); }
There can be many gears on a bike, but, for the sake of simplicity, this bike has only three gears: FirstGear
, SecondGear
, and ThirdGear
. Below are the implementations of the gears:
class FirstGear extends GearState{ FirstGear(Bike bike) { super(bike); } @Override public void gearUp() { System.out.println("Moving Up from FirstGear to SecondGear"); bike.gearState = new SecondGear(bike); } @Override public void gearDown() { System.out.println("Already in the FirstGear - cannot go lower"); } }
If you try to gearDown
when you are in the FirstGear
, you have no lower gear than the FirstGear
.
Therefore, it does nothing. But, when you try to gearUp
, naturally, you move up to the SecondGear
. The code below nicely demonstrates that.
Let's see the other gear states.
class SecondGear extends GearState{ SecondGear(Bike bike) { super(bike); } @Override public void gearUp() { System.out.println("Moving Up from SecondGear to ThirdGear"); bike.gearState = new ThirdGear(bike); } @Override public void gearDown() { System.out.println("Moving Down from SecondGear to FirstGear"); bike.gearState = new FirstGear(bike); } } class ThirdGear extends GearState { public ThirdGear(Bike bike) { super(bike); } @Override public void gearUp() { System.out.println("Already in the ThirdGear - cannot go higher"); } @Override public void gearDown() { System.out.println("Moving Down from ThirdGear to SecondGear"); bike.gearState = new SecondGear(bike); } }
Now, it is time to see it running. Below is the sample main method that demonstrates different state changes.
public class StateDemo { public static void main(String[] args) { Bike bike = new Bike(); bike.gearDown(); bike.gearUp(); bike.gearUp(); bike.gearUp(); bike.gearUp(); bike.gearDown(); bike.gearDown(); bike.gearDown(); } }
When you run the code above, the following represents the console output.
Already in the FirstGear
— cannot go lower
Moving Up from FirstGear
to SecondGear
Moving Up from SecondGear
to ThirdGear
Already in the ThirdGear
— cannot go higher
Already in the ThirdGear
— cannot go higher
Moving Down from ThirdGear
to SecondGear
Moving Down from SecondGear
to FirstGear
FirstGear
—
cannot go lower
Conclusion
If you have many States to keep up with and there are some complex relations between them, the State pattern is the right solution. It will keep your main class, in this case, Bike
, focused on its job. Later on, if you would like to add or remove new states, this will be less difficult.
Hope you enjoyed this demonstration!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK