Learning state mode of design mode

State mode

State Pattern is a behavioral pattern.

Include roles

Allows an object to change its behavior when its internal state changes.

The main solution of state mode is when the conditional expression controlling the state of an object is too complex.Complex judgment logic can be simplified by transferring the judgment logic of States to a series of classes representing different states.

1 Context: It defines the interfaces required by the client program and maintains an instance of a specific state role, delegating state-related operations to the current Concrete State object.

2 Abstract State: Defines an interface to encapsulate state-related behavior using a context.

3 Concrete State: An interface that implements an abstract state definition.

Class Diagram of State Mode

Create State Interface

/**
  * Create an interface that all state classes need to implement
  */
public interface State {
   /**
     * Defines the behavior of all state implementation classes
     */
   public void doAction(Context context);
}

Create implementation classes for interfaces

/**
  * Implementation class in state A
  */
public class AState implements State {
 
   public void doAction(Context context) {
        // do something
        System.out.println("now status is A");
        // Set the next state to B
        context.setState(new BState());
    }

    public String toString(){
        return "this is AState";
    }
}

/**
  * Implementation Class in State B
  */
public class BState implements State {
 
    public void doAction(Context context) {
        // do something
        System.out.println("now status is B");
        // Set the next state to C
        context.setState(new CState());
    }

    public String toString(){
        return "this is BState";
    }
}

/**
  * Implementation Class in C State
  */
public class CState implements State {
 
    public void doAction(Context context) {
        // do something
        System.out.println("now status is C");
        // Set the next state to null
        context.setState(null);

    }

    public String toString(){
        return "this is CState";
    }
}

Create Context Class

/**
 * Define the current state
 *
 */
public class Context {
    State state;

    public Context(State state) { //Define the initial state of the Context
        super();
        this.state = state;
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
        System.out.println("The current status is:" + state);
    }
    public void start(){
        if(state != null){
            state.doAction(this); //Processing the request and pointing to the next state
        }else{
            System.out.print("now state is null");
        }

    }
}

Create main method

public class main {
    public static void main(String[] args) {
        Context context = new Context(new AState());
        context.start();
        context.start();
        context.start();
        context.start();
    }
}

// Output Results
now status is A
//The current status is: this is BState
now status is B
//The current status is: this is CState
now status is C
//Current status is: null
now state is null

An example of a workflow

Workflow is to control the state of one node by one to achieve node jump, and finally to control the process.

If there is a leave process initiated above, the first node at this time is the departmental leadership review, which will continue to go down. If not, there are two states, one is to directly reject the request, the leader said that the project is very urgent recently, no one can take time off, and the other is that the leave request you wrote is incorrect and needs to be returned and rewritten.After the audit is approved, it will go to the next node, and the HR department will review it. Of course, the HR can also reject the request, or you can make a rectification. After the HR audit is approved, you can take a vacation. At this time, you can also choose whether to send an Email or not.

/**
 * Node Interface
 * @author gh
 *
 */
public abstract class Node {
    private static String name; //Current Node Name
    //Node Jump
    public abstract void nodeHandle(FlowContext context);
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    
}

Equivalent to the State class, where a node name is maintained.

/**
 * Lead Node
 * 
 * @author gh
 * 
 */
public class LeadNode extends Node {
    @Override
    public void nodeHandle(FlowContext context) {
        //Control the direction of the process based on the status of the current process
        //First determine if the process is over
        if(!context.isFlag()){
        System.out.println(context.getMessage()); //Read the application first
        if(context!=null&&3==context.getStatus()){ //Departmental Leadership Audit Only for Status Applied
            //Set the name of the current node
            setName("manager zhang");
            //Plus audit opinions
            context.setMessage(context.getMessage()+getName()+"Approval Passed;");
            //Approval Passed
            context.setStatus(0); //Audit Pass and Point to Next Node
            context.setNode(new HrNode());
            context.getNode().nodeHandle(context);
        }
    }else{
        System.err.println("The process has ended");
        }
    }
}

A leadership node has been created here to maintain the process of leadership review, which is handed over to HR audits.

public class HrNode extends Node {
 
    @Override
    public void nodeHandle(FlowContext context) {
        //First determine if the process is over
        if(!context.isFlag()){
        // Control the direction of the process based on the status of the current process
        if (context != null &&
                0 == context.getStatus()) { //HR auditing is not allowed until the previous level has passed
            // Set the name of the current node
            setName("HR plum");
            //Read previous level reviews and add your own comments
            System.out.println(context.getMessage()+getName()+"Approval Passed");
            // Approval Passed
            context.setStatus(0); //HR audits pass and point to the next node, setting status to end if there is no next node
            context.setFlag(true);
            
        }
        }else{
            System.out.println("The process has ended");
        }
    }
 
}

Here the HR audit passes and the node is set to the end state;

/**
 * Process Control
 * 
 * @author gh
 * 
 */
public class FlowContext {
    private boolean flag; // Represents the end of the process
    /**
     * Process status 0: Pass 1: Reject 2. Return rectification 3. Applied
     * 
     */
    private int status;
 
    private String message; // news
    private Node node; // Node Information
    public boolean isFlag() {
        return flag;
    }
 
    public void setFlag(boolean flag) {
        this.flag = flag;
    }
 
    public int getStatus() {
        return status;
    }
 
    public void setStatus(int status) {
        this.status = status;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void setMessage(String message) {
        this.message = message;
    }
 
    public Node getNode() {
        return node;
    }
 
    public void setNode(Node node) {
        this.node = node;
    }
 
    public static boolean start(FlowContext context) {
        Node node = new LeadNode();
        context.setNode(node); // Set Initial Node
        context.setStatus(3); // Set status to In Application
        context.getNode().nodeHandle(context); // Initiate Request
        // Finally, you need to know if your application is successful
        //Determine that the current is the last node and the audit passes, and the process ends
        if("HR plum".equals(node.getName())&&0==context.getStatus()&&context.isFlag()){
            System.out.println("Approval Passed,Process End");
            return true;
        }else{
            System.out.println("Audit failed, process ended");
            return false;
        }
    }
 
    public FlowContext() {
        super();
    }
    
}

A process control class is maintained here, which is passed after the HR and LEAD nodes and maintained by them separately.
Finally, write a test class test:

public static void main(String[] args) {
    FlowContext context=new FlowContext();
       context.setMessage("My Wang Xiao-2, because there are things in 11 families, would like to take three more days off, I hope the company can review and pass");
    context.start(context); 
 }

The printout is as follows
My Wang Xiao-2, because there are things in 11 families, would like to take three more days off, I hope the company can review and pass
My Wang Xiao-2, because there are things in the eleven families, would like to take three more days off, I hope the company can pass the examination and approval of Manager Zhang; HR Li passed the examination and approval
Review and approval, process end;

This example just mimics a jump in workflow control state.The most important benefit of state mode is that it puts state judgment and control inside its server, so that the client does not need to write a lot of code judgment to control its node jump. In this way, we can process each node separately, and when the process flows to a node, we can write its own node flow method.Of course, there are many drawbacks of state mode, such as high class coupling, basically three classes to write at the same time, and many node classes will be created.

Keywords: Programming

Added by buckit on Thu, 09 Jan 2020 10:19:33 +0200