State Pattern: Allows an object to change its behavior when its internal state changes, and the object appears to modify its class. Its alias is Objects for States, and state mode is an object behavioral mode.
The state pattern consists of the following roles:
Context: The environment class, also known as the context class, is an object with multiple states. Due to the diversity of the state of the environment class and the different behavior of the object in different states, the state is separated to form a separate state class. Maintain an instance of the abstract state class State in the environment class, which defines the current state and is an object of a state subclass when implemented. State (abstract state class): It defines an interface to encapsulate behavior related to a particular state of the environment class, declares various methods corresponding to different states in the abstract state class, and implements these methods in its subclasses. Because the behavior of objects in different states may be different, the implementation of methods in different subclasses may be different and the same. Methods can be written in abstract state classes. ConcreteState (concrete state class): It is a subclass of abstract state class. Each subclass implements a state-related behavior of the environment class. Each concrete state class corresponds to a specific state of the environment. Different concrete state classes have different behaviors.
1. Main Advantages
(1) It encapsulates the transition rules of state. In the state mode, it can encapsulate the transition codes of state in the environment class or the specific state class. It can centralize the management of the transition codes instead of dispersing them in one business method. (2) Put all the behavior related to a state into a class, only need to inject a different state object to make the environment object have different behavior. (3) It allows state transition logic to be integrated with state objects rather than providing a huge block of conditional statements. State patterns allow us to avoid using huge conditional statements to interweave business methods and state transition codes. (4) The number of objects in the system can be reduced by allowing multiple environment objects to share one state object.
2. Main shortcomings
(1) The use of state mode will inevitably increase the number of classes and objects in the system, which will lead to the increase of system operation overhead. (2) The structure and implementation of state mode are complex. If used improperly, it will lead to confusion of program structure and code, and increase the difficulty of system design. (3) The state mode does not support the "Open-Close Principle" very well. Adding new state classes requires modifying the source code responsible for state transition, otherwise it can not be converted to the new state; and modifying the behavior of a state class also requires modifying the source code of the corresponding class.
3. Applicable Scenario
(1) The object's behavior depends on its state (such as some attribute values), and the change of state will lead to the change of behavior. (2) There are a large number of conditional statements related to object state in the code. The emergence of these conditional statements will lead to poor maintainability and flexibility of the code, can not easily increase and delete state, and lead to enhanced coupling between client classes and class libraries.
The mode of state in the glory of the king (Li Xinguang, Dark Form):
/** * 2018/12/6 * Switching class of state mode * * @author machuanpeng */ public class LiXinContext { private int stateInt; private State state; public LiXinContext() { this.stateInt = 0; this.state = new OriginalState(); } public State getState() { return state; } public void setState(State state) { this.state = state; } public int getStateInt() { return stateInt; } public void setStateInt(int stateInt) { this.stateInt = stateInt; } public void bigOperation() { // Release the big move state.bigOperation(this); } }
/** * 2018/12/6 * State * * @author machuanpeng */ public abstract class State { public void bigOperation(LiXinContext context) }
/** * 2018/12/6 * Initial form * * @author machuanpeng */ public class OriginalState extends State { public void bigOperation(LiXinContext context) { if(context.getStateInt()==0){ System.out.println("There is no big trick in primitive form!"); }else{ context.setState(new LightState()); context.bigOperation(); } } }
/** * 2018/12/6 * Light form * * @author machuanpeng */ public class LightState extends State { public void bigOperation(LiXinContext context) { if(context.getStateInt()==1){ System.out.println("Light form, three lights!"); }else if(context.getStateInt()<1){ context.setState(new OriginalState()); context.bigOperation(); }else if(context.getStateInt()>1){ context.setState(new DarkState()); context.bigOperation(); } } }
/** * 2018/12/6 * Dark form * * @author machuanpeng */ public class DarkState extends State { public void bigOperation(LiXinContext context) { if(context.getStateInt()==2){ System.out.println("Pat the floor in a dark shape and bounce each other up! ____________"); }else{ context.setState(new LightState()); context.bigOperation(); } } }
Test:
public class Client { public static void main(String args[]) { LiXinContext context = new LiXinContext(); context.bigOperation(); context.setStateInt(1); context.bigOperation(); } }