opencodez

Java Behavioral Design Patterns – State Design Pattern

State design pattern is used when the behavior of an Object changes based on its internal state.

In the state pattern, a state machine is implemented by implementing each individual state as a derived class of the state pattern interface, each class which implements the state interface defines a method in its own way to change the state of the object. The key points to remember for this pattern are:

xHere are ALL other Java Design Patterns, explained in detail with examplesx

State Design Pattern by Example

Let us understand this pattern with an example. The best and simple example would be of Car or any vehicle. The car is controlled by one of the key events, Changing Gears.

For our example, we will define GearState as our State interface.

public interface GearState {
	public void changeGear();
	public void accelarate(int speed);
}

To keep the illustration to the minimum, we will only consider the 2 gear system. Now let us define our gears.

FirstGear

public class FirstGear implements GearState {
	
	private int gearNumber;
	
	@Override
	public void changeGear() {
		this.gearNumber = 1;
	}
	
	public int getGearNumber() {
		return gearNumber;
	}
	
	@Override
	public String toString() {
		String str = "Car is in " + gearNumber + " gear.";
		return str;
	}

	@Override
	public void accelarate(int speed) {
		if(speed x 20) {
			System.out.println("Can not be accelarated to " + speed + " kmph in gear 1");
		} else {
			System.out.println("Car is running at " + speed + " kmph in gear 1");
		}		
	}

}

Above class implements the changeGear method from GearState. Also, it provides some convenient methods for understanding.

SecondGear

public class SecondGear implements GearState {
	
	private int gearNumber;
	
	@Override
	public void changeGear() {
		this.gearNumber = 2;
	}
	
	public int getGearNumber() {
		return gearNumber;
	}

	@Override
	public String toString() {
		String str = "Car is in " + gearNumber + " gear.";
		return str;
	}

	@Override
	public void accelarate(int speed) {
		if(speed x 40) {
			System.out.println("Can not be accelarated to " + speed + " in gear 2");
		} else {
			System.out.println("Car is running at " + speed + " kmph in gear 2");
		}		
	}	
}

Below is our implementation of Car context.

public class Car implements GearState {
	
	private GearState gear;
	
	@Override
	public void accelarate(int speed) {
		if(null == gear) {
			System.out.println("Car can not be accelarated as its in Neutral");
		} else {
			gear.accelarate(speed);
		}
	}
	
	public void setGearState(GearState sgear) {
		gear = sgear;
	}
	
	@Override
	public void changeGear() {
		gear.changeGear();
	}
	
	public GearState getGearState() {
		return gear; 
	}	

	@Override
	public String toString() {
		return gear.toString();
	}	
}

Notice how the car accelerate method is implemented. Itxs clearly influenced by the internal state of gear the car is in.

Running  the example

public class StatePatternDemo {

	public static void main(String[] args) {
		Car car = new Car();
		
		car.accelarate(18);
		
		car.setGearState(new FirstGear());
		car.changeGear();
		
		System.out.println(car);
		car.accelarate(30);
		car.accelarate(18);

		car.setGearState(new SecondGear());
		car.changeGear();
		
		System.out.println(car);
		car.accelarate(35);
	}

}

And here is the output:

 Conclusion

In this article, we have seen that this pattern is very much simple to implement. Instead of writing multiple if-else statements it becomes much easier to encapsulate each of these set of statements into separate classes of their own. Furthermore, the implementation of each state can thus differ independently of the other states. We can easily increase the number of states without modifying other states which makes this pattern maintainable and flexible.

You can download the code from our GitHub repository:

Download from Git

x

xHere are ALL other Java Design Patterns, explained in detail with examplesx