Thursday, September 20, 2012

Going Technical ....State Design Pattern

Just completed a hectic schedule , here I am back to write something for you!!!. Well today lets look at another GOF design pattern known as State pattern

Let's start this again with a simple example. We all know that humans are very sensitive towards their environment. If the environment is good and nice , a human living in that environment would feel good. If the environment is really hostile to a human living in that environment , he or she would feel really bad about it.If the environment is neither good nor bad then a human living in that environment would feel no difference. He or she will probably be in a neutral state in his or her mind.

It seems that the mental or physical state of the human is affected by the environment where he or she lives.We could consider this as "The state of the human's mind and body is effected by the environment in which he or she lives". It is obvious that depending on the mood of the human his or her reactions would be different. We can transform this understanding to the programming world as below,

"The behavior of an Object is a function of it's state". In the above analogy object is "The Human" , state is "The Mood" of the human and the nature of the environment is the triggering point for the state transition from one to another

In the programming world you may sometimes need to change the behavior of a given object based on the state of the object. In this case each state can be represented as a different class. When the object receives some form of a trigger it will change it's internal state. As a result of that the behavior of the object will change.

Let's put everything in to codes now ....

We have a top level interface representing a general "Mood" of a human


package sg.blogspot.dranilev;

public interface Mood {
   public String talk();
   public String think();
   public String work();
   public String walk();
}

Some moods that human may be having,

This is the good mood,

package sg.blogspot.dranilev;

public class GoodMood implements Mood {

   @Override
   public String talk() {
     return "Nice and cool";
   }

   @Override
   public String think() {
     return "Calm and focused , relaxed";
   }

   @Override
   public String work() {
     return "enjoy and focused well";
   }

   @Override
   public String walk() {
     return "Not in a hurry";
   }

}

This is a really bad mood,
package sg.blogspot.dranilev;

public class BadMood implements Mood {

   @Override
   public String talk() {
     return "Not Nice";
   }

   @Override
   public String think() {
     return "Confused , Unable to focus";
   }

   @Override
   public String work() {
     return "Stressful , not able to meet targets";
   }

   @Override
   public String walk() {
     return "In a hurry";
   }

}

This is a neutral mood ,
package sg.blogspot.dranilev;

public class NeutralMood implements Mood {

   @Override
   public String talk() {
     return "Normal talking";
   }

   @Override
   public String think() {
     return "Normal Thinking";
   }

   @Override
   public String work() {
     return "Normal working";
   }

   @Override
   public String walk() {
     return "Normal walking";
   }

}

Human , who has a mood at all the times,


package sg.blogspot.dranilev;

public class Human {

   private Mood mood;

   public String respondToTalk(){
     return getMood().talk();
   }

   public String respondToWalk(){
     return getMood().walk();
   }

   public String respondToWork(){
     return getMood().work();
   }

   public String respondToThought(){
     return getMood().think();
   }
   public Mood getMood() {
     return mood;
   }

   public void setMood(Mood mood) {
     this.mood = mood;
   }
}

Lets see the environment where human is living. Also see how the human changes his or her mood depending on the changes happened to the environment


package sg.blogspot.dranilev;

public class Environment {

   private Human humanInEnvironment = null;

   public void changeToHostileEnvironment(){
   //current environment is hostile , humans in this environment will be effected
     Mood badMood = new BadMood();
     getHumanInEnvironment().setMood(badMood);
   }

   public void changeToFriendlyEnvironment(){
     //current environment is friendly.
     Mood goodMood = new GoodMood();
     getHumanInEnvironment().setMood(goodMood);
   }

   public void changeToNormalEnviroment(){
     //current environment is normal
     Mood neutralMood = new NeutralMood();
     getHumanInEnvironment().setMood(neutralMood);
   }

   public Human getHumanInEnvironment() {
     return humanInEnvironment;
   }

   public void setHumanInEnvironment(Human humanInEnvironment) {
     this.humanInEnvironment = humanInEnvironment;
   }

}

Now that , lets see how Human changes his or her mood depending on the changes that happen to the environment


package sg.blogspot.dranilev;

public class StateExampleMain {

   public static void main(String[] args) {
     //Environment
     Environment environmnet = new Environment();
     //A human living in this environment,
     Human humanLivingInEnvironment = new Human();
     environmnet.setHumanInEnvironment(humanLivingInEnvironment);
     //Suddenly environment changes to a hostile environment
     environmnet.changeToHostileEnvironment();
     //lets check how the human in this environment has been effected
     checkHumanState(environmnet);
     //Now , environment changes to a friendly one
     environmnet.changeToFriendlyEnvironment();
     checkHumanState(environmnet);
     //Now , environment changes to a neutral one
     environmnet.changeToNormalEnviroment();
     checkHumanState(environmnet);
   }

   private static void checkHumanState(Environment environmnet){
     System.out.println("printing current state (Start)");
    System.out.println(environmnet.getHumanInEnvironment().respondToTalk());
    System.out.println(environmnet.getHumanInEnvironment().respondToThought());
    System.out.println(environmnet.getHumanInEnvironment().respondToWalk());
    System.out.println(environmnet.getHumanInEnvironment().respondToWork());
     System.out.println("printing current state (End)");
}

}