In the process of software development, some objects in the application may make different behaviors according to different situations. We call this kind of object stateful object, and one or more dynamically changing attributes that affect the behavior of the object state. When stateful objects interact with external events, their internal state will change, so that their behavior will also change. If people are happy and sad, different emotions have different behaviors. Of course, the outside world will also affect their emotional changes.
For this stateful object programming, the traditional solution is to consider all these possible situations, and then use if else or switch case statements to judge the state, and then deal with different situations. However, it is obvious that this method has natural disadvantages for complex state judgment. The conditional judgment statements will be too bloated, poor readability, non extensible and difficult to maintain. When adding a new state, a new if else statement should be added, which violates the "opening and closing principle" and is not conducive to the expansion of the program.
The above problems can be well solved if the "state mode" is adopted. The solution idea of state mode is: when the conditional expression controlling the state transition of an object is too complex, extract the relevant "judgment logic" and represent it with different classes. In which case the system is in, directly use the corresponding state class objects for processing, so as to simplify the original complex logic judgment and eliminate if else Redundant statements such as switch case make the code more hierarchical and have good scalability.
Definition and characteristics of state mode
Definition of State mode
For stateful objects, the complex "judgment logic" is extracted into different state objects, allowing the state object to change its behavior when its internal state changes.
State mode is an object behavior mode
advantage
- The structure is clear, and the state mode localizes the behaviors related to a specific state into one state, and separates the behaviors in different states to meet the "single responsibility principle".
- Display the state transition to reduce the interdependence between objects. Introducing different states into independent objects will make the state transition more explicit and reduce the interdependence between objects.
- The responsibilities of the status class are clear, which is conducive to the expansion of the program. It is easy to add new states and transitions by defining new subclasses.
shortcoming
- The use of state mode will inevitably increase the number of classes and objects in the system.
- The structure and implementation of state mode are complex. Improper use will lead to confusion of program structure and code.
- The state mode does not support the opening and closing principle very well. For the state mode that can switch states, adding a new state class requires modifying the source code responsible for state transformation, otherwise it cannot switch to the new state, and modifying the behavior of a state class also requires modifying the source code of the corresponding class.
Structure and implementation of state pattern
State mode packages the behavior of objects changed by the environment in different state objects. Its intention is to make an object change its behavior when its internal state changes. Now let's analyze its basic structure and implementation method.
1. Structure of the model
The status mode contains the following main roles.
- Context role: also known as context, it defines the interface required by the client, internally maintains a current state, and is responsible for switching specific states.
- Abstract State role: define an interface to encapsulate the behavior corresponding to a specific State in an environment object. There can be one or more behaviors.
- Concrete State role: implement the behavior corresponding to the abstract state, and switch the state if necessary.
Its structure is shown in Figure 1.
2. Implementation of mode
The implementation code of status mode is as follows:
public class StatePatternClient { public static void main(String[] args) { Context context = new Context(); //Create environment context.Handle(); //Processing requests context.Handle(); context.Handle(); context.Handle(); } } //Environment class class Context { private State state; //Defines the initial state of the environment class public Context() { this.state = new ConcreteStateA(); } //Set new status public void setState(State state) { this.state = state; } //Read status public State getState() { return (state); } //Processing requests public void Handle() { state.Handle(this); } } //Abstract state class abstract class State { public abstract void Handle(Context context); } //Specific status class A class ConcreteStateA extends State { public void Handle(Context context) { System.out.println("Current status is A."); context.setState(new ConcreteStateB()); } } //Specific status class B class ConcreteStateB extends State { public void Handle(Context context) { System.out.println("Current status is B."); context.setState(new ConcreteStateA()); } }
The running results of the program are as follows:
Current status is A. Current status is B. Current status is A. Current status is B.
Application examples of state mode
[example] use "state mode" to design a state conversion program for students' grades.
Analysis: this example includes three states of "failed", "medium" and "excellent". When the student's score is less than 60, it is "failed", when the score is greater than or equal to 60 and less than 90, it is "medium", and when the score is greater than or equal to 90, it is "excellent". We use the state mode to realize this program.
First, define an abstract state class (AbstractState), which contains environment attribute, state name attribute and current score attribute, plus and minus score method addScore(intx) and abstract method checkState() to check the current state.
Then, define the "failed" state class LowState, "medium" state class MiddleState and "excellent" state class HighState, which are specific state classes and implement the checkState() method, which is responsible for checking their own state and converting according to the situation.
Finally, the environment class (ScoreContext) is defined, which contains the current state object and the method add(int score) for adding and subtracting points. The customer class uses this method to change the score state. Figure 2 shows its structure.
The program code is as follows:
public class ScoreStateTest { public static void main(String[] args) { ScoreContext account = new ScoreContext(); System.out.println("Student achievement status test:"); account.add(30); account.add(40); account.add(25); account.add(-15); account.add(-25); } } //Environment class class ScoreContext { private AbstractState state; ScoreContext() { state = new LowState(this); } public void setState(AbstractState state) { this.state = state; } public AbstractState getState() { return state; } public void add(int score) { state.addScore(score); } } //Abstract state class abstract class AbstractState { protected ScoreContext hj; //environment protected String stateName; //Status name protected int score; //fraction public abstract void checkState(); //Check current status public void addScore(int x) { score += x; System.out.print("add:" + x + "Points,\t Current score:" + score); checkState(); System.out.println("Points,\t Current status:" + hj.getState().stateName); } } //Specific status: failed class LowState extends AbstractState { public LowState(ScoreContext h) { hj = h; stateName = "fail,"; score = 0; } public LowState(AbstractState state) { hj = state.hj; stateName = "fail,"; score = state.score; } public void checkState() { if (score >= 90) { hj.setState(new HighState(this)); } else if (score >= 60) { hj.setState(new MiddleState(this)); } } } //Specific status class: medium class MiddleState extends AbstractState { public MiddleState(AbstractState state) { hj = state.hj; stateName = "secondary"; score = state.score; } public void checkState() { if (score < 60) { hj.setState(new LowState(this)); } else if (score >= 90) { hj.setState(new HighState(this)); } } } //Specific status: excellent class HighState extends AbstractState { public HighState(AbstractState state) { hj = state.hj; stateName = "excellent"; score = state.score; } public void checkState() { if (score < 60) { hj.setState(new LowState(this)); } else if (score < 90) { hj.setState(new MiddleState(this)); } } }
The running results of the program are as follows:
Student achievement status test: Plus: 30 points, Current score: 30 points, Current status: fail Plus: 40 points, Current score: 70 points, Current status: medium Plus: 25 points, Current score: 95 points, Current status: excellent add:-15 Points, Current score: 80 points, Current status: medium add:-25 Points, Current score: 55 points, Current status: fail
Application scenario of state mode
You can usually consider using state mode in the following cases.
- When an object's behavior depends on its state and it must change its behavior according to its state at run time, you can consider using state mode.
- An operation contains a large branch structure, and these branches depend on the state of the object. Extension of state mode