The State Pattern allows an object to alter its behavior when its internal state changes. The object will appear to change its class
What does it mean for an object to "appear to change its class?" Think about it from the perspective of a client: if an object you are using can completely change its behavior, then it appears to you that the object is actually instantiated from another class. In reality, however you know that we are using composition to give the appearance of a class change by simply referencing different state objects.
Motivation
Let us look at detailed example:
Consider the life of a person, it has 4 states - childhood, boyhood, youth and old-age. So
now if you are youth, you do something different and when you are boy you do different.
So the logic uses nested ifs to find what the state is and then perform logic.
The State Pattern
State transitions can be controlled by State Classes or by Context Classes.
Objects are often discussed in terms of having a "state" that describes their exact conditions in a given time, based upon the values of their properties. The particular values of the properties affect the object's behavior.
Now if we use State Design Pattern here, we can get rid of this messy if else code in Life Class and also make it flexible.
What we are doing here is implementing the behaviours that are appropriate for the state we are in. In some cases this behaviour includes moving the Life forward to new state.
We will have similar kind of classes for 'YouthState' and 'OldState' also ...
From the above explanation we came to know that State Design Pattern is a fully encapsulated, self-modifying Strategy Design Pattern.
Advantage and Disadvantage
In general think of strategy pattern as a flexible alternative to subclassing; if you use inheritence to define the behaviour of a subclass then you are stuck with that behaviour even if you need to change it. With Strategy you can change the behaviour by composing with a different object.
Disadvantage: By encapsulating state behaviour into seperate classes, you'll always end up with more classes in your design. That's often the price you pay for flexibility.
What does it mean for an object to "appear to change its class?" Think about it from the perspective of a client: if an object you are using can completely change its behavior, then it appears to you that the object is actually instantiated from another class. In reality, however you know that we are using composition to give the appearance of a class change by simply referencing different state objects.
Motivation
- State charts are often used to describe dynamic behavior
- The "traditional" way to implement state transitions often involves complicated, nested if statements
public boolean isDark()
{
if(swichLight().equalsIgnoreCase("off"))
return true;
else
return false;
}
Let us look at detailed example:
Consider the life of a person, it has 4 states - childhood, boyhood, youth and old-age. So
now if you are youth, you do something different and when you are boy you do different.
So the logic uses nested ifs to find what the state is and then perform logic.
//With out using StateDesign Pattern
public class Life
{
final static int CHILD = 0;
final static int BOY = 1;
final static int YOUTH = 2;
final static int OLD = 3;
int state = CHILD;
public void children(){
if(state == CHILD){
System.out.println("Go and Play...");
state = BOY;
}
else if(state == BOY)
System.out.println("Don't behave like a kid");
else if(state == YOUTH)
System.out.println("Don't behave like a kid");
else if(state == OLD)
System.out.println("Don't behave like a kid");
}
public void schoolBoy(){
if(state == CHILD)
System.out.println("grow up...");
else if(state == BOY){
System.out.println("Its time to go to school");
state = YOUTH;
}
else if(state == YOUTH)
System.out.println("Don't behave like a boy");
else if(state == OLD)
System.out.println("Don't behave like a boy");
}
public void youngGeneration(){
if(state == CHILD)
System.out.println("grow up...");
else if(state == BOY)
System.out.println("grow up...");
else if(state == YOUTH){
System.out.println("Right time to achieve my goals...");
state = OLD;
}
else if(state == OLD)
System.out.println("You are no longer youth");
}
public void oldGeneration(){
if(state == CHILD)
System.out.println("grow up...");
else if(state == BOY)
System.out.println("grow up...");
else if(state == YOUTH){
System.out.println("grow up...");
state = OLD;
}
else if(state == OLD)
System.out.println("I can guide you all");
}
public String toString(){
return state+"";
}
// Other methods...
}
- Delegate the responsibility of handling state transitions to encapsulations of the states
- Participants:
- An abstract State
- Several concrete State classes
- A Context
State transitions can be controlled by State Classes or by Context Classes.
Objects are often discussed in terms of having a "state" that describes their exact conditions in a given time, based upon the values of their properties. The particular values of the properties affect the object's behavior.
Now if we use State Design Pattern here, we can get rid of this messy if else code in Life Class and also make it flexible.
//With State Design Pattern
public interface State{
public void childhood();
public void boyhood();
public void youth();
public void old();
}
public class ChildHoodState implements State{
Life life;
public ChildHoodState(Life life){
this.life = life;
}
public void childhood(){
System.out.println("Go and Play...");
life.setState(life.boyHoodState);
}
public void boyhood(){
System.out.println("Don't behave like a kid");
}
public void youth(){
System.out.println("Don't behave like a kid");
}
public void old(){
System.out.println("Don't behave like a kid");
}
}
public class BoyHoodState implements State{
Life life;
public BoyHoodState(Life life){
this.life = life;
}
public void childhood(){
System.out.println("Grow up.. ");
}
public void boyhood(){
System.out.println("Its time to go to school");
life.setState(life.youthState);
}
public void youth(){
System.out.println("Don't behave like a boy");
}
public void old(){
System.out.println("Don't behave like a boy");
}
}
public class YouthState implements State{
Life life;
public YouthState(Life life){
this.life = life;
}
public void childhood(){
System.out.println("Grow up...");
}
public void boyhood(){
System.out.println("Grow up...");
}
public void youth(){
System.out.println("Right time to achieve my goals...");
life.setState(life.oldState);
}
public void old(){
System.out.println("You are no longer youth");
}
}
public class OldState implements State{
Life life;
public OldState(Life life){
this.life = life;
}
public void childhood(){
System.out.println("Grow up...");
}
public void boyhood(){
System.out.println("Grow up...");
}
public void youth(){
System.out.println("Grow up...");
}
public void old(){
System.out.println("I can guide you all");
}
}
public class Life{
// All the States
State childHoodState;
State boyHoodState;
State youthState;
State oldState;
// initialise them
State state = childHoodState;
public Life(){
childHoodState = new ChildHoodState(this);
boyHoodState = new BoyHoodState(this);
youthState = new YouthState(this);
oldState = new OldState(this);
}
// Delegate to current state
public void children(){
state.childhood();
}
public void schoolBoy(){
state.boyhood();
}
public void youngGeneration(){
state.youth();
}
public void oldGeneration(){
state.old();
}
// for transition of state
public void setState(State state){
this.state = state;
}
// Many other methods needed... including getters and setters of each State
}
public class TestLife{
public static void main(String[] args) {
Life life = new Life();
System.out.println(life);
life.children();
life.schoolBoy();
life.youngGeneration();
life.oldGeneration();
System.out.println(life);
}
}
What we are doing here is implementing the behaviours that are appropriate for the state we are in. In some cases this behaviour includes moving the Life forward to new state.
We will have similar kind of classes for 'YouthState' and 'OldState' also ...
From the above explanation we came to know that State Design Pattern is a fully encapsulated, self-modifying Strategy Design Pattern.
Advantage and Disadvantage
In general think of strategy pattern as a flexible alternative to subclassing; if you use inheritence to define the behaviour of a subclass then you are stuck with that behaviour even if you need to change it. With Strategy you can change the behaviour by composing with a different object.
Disadvantage: By encapsulating state behaviour into seperate classes, you'll always end up with more classes in your design. That's often the price you pay for flexibility.
nice
ReplyDeleteYour program is not working, can you help me?
ReplyDeleteI needed to understand this program