Friday, January 30, 2015

State Design Pattern in Java

Introduction

Over the course of this article, we will examine State design pattern in java with help of realtime examples.
The State design pattern belongs to the behavioral family of pattern that deals with the runtime object behavior based on the current state. The definition of State Design Pattern as per the original Gang of Four book is; “Allows an object to alter its behavior when its internal state changes. The object will appear to change its class”.

How State pattern works?

  1. Define an object that represent various states that object can be. Remember state machine.
  2. Define a context object, whose behavior varies as its state object changes.

Real time use case

State pattern is one of the heavily used pattern in game development. The game character can be in different states such as healthy, surviving and dead. When character is healthy, it allows user to fires at enemies with different weapons. When surviving state its health gets critical, and when its health reaches to 0, the character is said to be in dead state where the game is over.
Let us implement this use case without using State design pattern. It can be achieved by using set of if else conditional checks, as shown in the following code snippets.

Player.java

The Player class defines the different actions a player can perform.
public class Player {

 public void attack() {
  System.out.println("Attack");
 }

 public void fireBumb() {
  System.out.println("Fire Bomb");
 }

 public void fireGunblade() {
  System.out.println("Fire Gunblade");
 }

 public void fireLaserPistol() {
  System.out.println("Laser Pistols");
 }

 public void firePistol() {
  System.out.println("Fire Pistol");
 }

 public void survive() {
  System.out.println("Surviving!");
 }

 public void dead() {
  System.out.println("Dead! Game Over");
 }

}
Now let us define our game context class which defines the different actions conditionally depends on the state of the player.

GameContext.java

public class GameContext {

 private Player player = new Player();

 public void gameAction(String state) {
  if (state == "healthy") {
   player.attack();
   player.fireBumb();
   player.fireGunblade();
   player.fireLaserPistol();
  } else if (state == "survival") {
   player.survive();
   player.firePistol();
  } else if (state == "dead") {
   player.dead();
  }
 }
}
In the above code snippet, the gameAction method contains too many conditional blocks for performing different game action based on the state of player. This is a real problem of code maintainability. this can be avoided using State design pattern.

State Design Pattern Example

Before we begin with the state design pattern, let us have a look into the class design.
State Design Pattern Java1. Define an interface named PlayerState that defines action method. The access() method takes the instance of Player class. This is required to perform player action.
public interface PlayerState { 
 void action(Player p);
}
2. Define three different classes that represents the different states. In this example, I have named them as HealthyStateSurvivalStateDeadState. All of three classes implementsPlayerState interface and provides the specific action() method implementation.
public class HealthyState implements PlayerState {

 @Override
 public void action(Player p) {
  p.attack();
  p.fireBumb();
  p.fireGunblade();
  p.fireLaserPistol();
 }
}

public class SurvivalState implements PlayerState {

 @Override
 public void action(Player p) {
  p.survive();
  p.firePistol();
 }
}

public class DeadState implements PlayerState {

 @Override
 public void action(Player p) {
  p.dead();
 }
}
3. The GameContxt class contains two setState() method composition. Now we will remove all of the code to conditional logic.
public class GameContext {
 
 private PlayerState state = null;
 private Player player = new Player();

 public void setState(PlayerState state) {
  this.state = state;
 }

 public void gameAction() {
  state.action(player);
 }
}
4. Thats All! Let us test our code using below GameTest class.
public class GameTest {

 public static void main(String[] args) {

  GameContext context = new GameContext();

  context.setState(new HealthyState());
  context.gameAction();
  System.out.println("*****");

  context.setState(new SurvivalState());
  context.gameAction();
  System.out.println("*****");

  context.setState(new DeadState());
  context.gameAction();
  System.out.println("*****");

 }
}

Output

Attack
Fire Bomb
Fire Gunblade
Laser Pistols
*****
Surviving!
Fire Pistol
*****
Dead! Game Over
*****




Reference: http://javatechig.com/design-patterns

Strategy Design Pattern in Java

Introduction

The Strategy design pattern belongs to the behavioral family of pattern that deals with change the behavior of a class by changing the internal algorithm at runtime without modifying the class itself. This allows extensibility and loose coupling of objects.
The definition of State Design Pattern as per the  original Gang of Four book is; “Defines a set of encapsulated algorithms that can be swapped to carry out a specific behavior”

Real time use case

  1. A data compression software like winzip, provides different algorithms to perform gip, gzip, tar, jar, 7zip format. At runtime client chooses which type of algorithm to be performed.
  2. Email client like outlook, supports various email types such as plain text and HTML type. It allow client to choose the email format.

How Strategy pattern works?

The Strategy pattern is simple yet popular design pattern, mostly works together with State pattern. Following are the steps involved to create strategy design pattern:
  1. Implement a Strategy interface for your strategy objects. This interface defines the strategy object behavior.
  2. Implement Concrete Strategy classes that implements the Strategy interface defined in the above step
  3. Create a Context class and maintain the reference to strategy object. Create setter and getter method  to allow access to strategy object

Strategy Design Pattern Example

Let us take the example of a program that perform various number sorting algorithm such as Insertion sort, Selection Sort, Merge Sort etc. It allows client to choose which type of sorting he would like to perform.
The above use case can be represented in the following class diagram
Strategy Design Pattern Java
SortingStrategy.java
public interface SortingStrategy {

 public void sort(int[] numbers);

}
SelectionSort.java
public class SelectionSort implements SortingStrategy {

 @Override
 public void sort(int[] numbers) {
  System.out.println("Selection Sort!");

  int i, j, first, temp;
  for (i = numbers.length - 1; i > 0; i--) {
   first = 0;
   for (j = 1; j <= i; j++) {
    if (numbers[j] > numbers[first])
     first = j;
   }
   temp = numbers[first];
   numbers[first] = numbers[i];
   numbers[i] = temp;
  }
  
  System.out.println(Arrays.toString(numbers));
 }
}
InsertionSort.java
public class InsertionSort implements SortingStrategy {

 @Override
 public void sort(int[] numbers) {
  System.out.println("Insertion Sort!");

  for (int i = 1; i < numbers.length; i++) {
   int temp = numbers[i];
   int j;
   for (j = i - 1; (j >= 0) && (numbers[j] > temp); j--) {
    numbers[j + 1] = numbers[j];
   }
   numbers[j + 1] = temp;
  }

  System.out.println(Arrays.toString(numbers));
 }
}
public class SortingContext {
 
 private SortingStrategy strategy;
 
 public void setSortingMethod(SortingStrategy strategy) {
  this.strategy = strategy;
 }
 
 public SortingStrategy getStrategy() {
  return strategy;
 }
 
 public void sortNumbers(int[] numbers){
  strategy.sort(numbers);
 }
}
TestMain.java
Here is how client using strategy pattern
public class TestMain {

 public static void main(String[] args) {
  
  int numbers[] = {20, 50, 15, 6, 80};
  
  SortingContext context = new SortingContext();
  context.setSortingMethod(new InsertionSort());
  context.sortNumbers(numbers);
  
  System.out.println("***********");
  context.setSortingMethod(new SelectionSort());
  context.sortNumbers(numbers);
  
 }
}
Output
Insertion Sort!
[6, 15, 20, 50, 80]
***********
Selection Sort!
[6, 15, 20, 50, 80]