Monday, December 18, 2006

Implementing State Pattern in Java

In the previous post, I described a little about the State design pattern and it's relation to the Strategy pattern. In this post, I will show how to implement the State Pattern in Java. The following is the UML diagram for the State Pattern. A description and sample code for the example follows:State Pattern UML
  • Context: Acts as the interface to clients. The Context object maintains an instance of a ConcreteState subclass that represents the current state. The context delegates the requests to the concrete state object that represents the current state. Typically, the context passes itself as an argument to the current state object, which changes the current state of the context.
    public class StateContext {
    private State acceptedState;
    private State requestedState;
    private State grantedState;

    private State state;

    public StateContext() {
    acceptedState = new AcceptedState();
    requestedState = new RequestedState();
    grantedState = new GrantedState();
    state = null;
    }

    public void acceptApplication() {
    this.state = acceptedState;
    }

    public void requestPermission() {
    state.requestPermission(this);
    }

    public void grantPermission() {
    state.grantPermission(this);
    }

    public String getStatus() {
    return state.getStatus();
    }

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

    public State getAcceptedState() {
    return acceptedState;
    }

    public State getGrantedState() {
    return grantedState;
    }

    public State getRequestedState() {
    return requestedState;
    }

    }
    StateContext.java
  • State: An interface for encapsulating the behavior associated with a particular state of the Context.
    public interface State {
    public void grantPermission(StateContext ctx);
    public void requestPermission(StateContext ctx);
    public String getStatus();
    }
    State.java
  • Concrete State subclasses: Define the behaviour associated each state.
    public class RequestedState implements State {
    public void grantPermission(StateContext ctx) {
    System.out.println("Granting Permission");
    ctx.setState(ctx.getGrantedState());
    }
    public void requestPermission(StateContext ctx){
    System.out.println("Permission already requested");
    }
    public String getStatus() {
    return "Requested permission";
    }
    }
    RequestedState.java
    public class AcceptedState implements State {
    public void grantPermission(StateContext ctx) {

    }
    public void requestPermission(StateContext ctx){
    System.out.println("Requesting permission");
    ctx.setState(ctx.getRequestedState());
    }

    public String getStatus() {
    return "Request Received";
    }
    }
    AcceptedState.java
    public class GrantedState implements State {
    public void grantPermission(StateContext ctx) {
    System.out.println("Invalid state");
    }
    public void requestPermission(StateContext ctx){
    System.out.println("Invalid state");
    }

    public String getStatus() {
    return "Granted";
    }
    }
    GrantedState.java
  • Client
    public class StateClient {
    public static void main(String[]args) {
    StateContext ctx = new StateContext();
    ctx.acceptApplication();
    ctx.requestPermission();
    ctx.grantPermission();
    System.out.println(ctx.getStatus());
    }
    }
    StateClient.java

4 comments:

  1. I like the code and have learned a lot from it. But, this code is a bit against the open close principle. If I have another state to be added other than the stated ones, then I should implement on all classes. I think this is not a good approach. Other than that I have used it for my understanding thankyou.

    ReplyDelete
  2. I really apreciate this blog, your explanations are quite clear. But I'm still wondering when use patters, I mean if I have a class, for instance Book, and I need to keep the state of the book, I mean In Stock, etc. I can have a property with the state, or I can implement the state pattern, which solution is better, how I can determine the proper one.....

    ReplyDelete
  3. State design pattern works on the concept of state change. Entire process life-cycle can be divided in multiple phases.With completion of each phase process exits from one state and enters in to another state.

    For example In JSF framework entire web request response lifecycle is divided in six phases:

    After completion of every phase process exits from a state and enters into another state. For example after RestoreValuePhase we can say ViewRestored as exit state and RequestApply as entering state .

    So to implement State design pattern It is required to divide entire process in such a way that It can be processed in multiple phases with every phase exit defining a state change.

    Now let's understand this with below code.


    Any project lifecycle can be divided in multiple phases like


    requirementAssessment
    Design
    Development
    QualityAssessment
    Deploy
    Closure



    So these are the phases used in below example

    Rules :

    1. We need to define a class where we can store the current state of the process. NextPhase class in below code is doing that.

    2. We need to define an Interface wherein we can provide the contact method that would be implemented in each phase.In below code ProjectPhase is doing that.


    Learn more about State design pattern here -- State Design Pattern

    http://efectivejava.blogspot.in/2013/09/java-state-design-patten-oops-state.html?utm_source=BP_recent

    ReplyDelete

Popular Posts