Structure of state mode
In one sentence, the state pattern packages the behavior of the studied object in different state objects, and each state object belongs to a subclass of an abstract state class. The intention of state pattern is to make an object change its behavior when its internal state changes. The schematic class diagram of state mode is as follows:
Role of state mode
- Context role, also known as context: defines the interface of interest to the client, and retains an instance of a specific state class. An instance of this concrete state class gives the existing state of this environment object.
- Abstract state role: define an interface to encapsulate the behavior corresponding to a specific state of the Context object.
- Concrete state role: each concrete state class implements the behavior corresponding to a state of the environment (Context).
Sample code
Environment role class
public class Context { //Holds an object instance of type State private State state; public void setState(State state) { this.state = state; } /** * Interface methods of interest to users */ public void request(String sampleParameter) { //Transfer state to handle state.handle(sampleParameter); } }
Abstract state class
public interface State { /** * Processing corresponding to status */ public void handle(String sampleParameter); }
Specific state class
public class ConcreteStateA implements State { @Override public void handle(String sampleParameter) { System.out.println("ConcreteStateA handle : " + sampleParameter); } }
public class ConcreteStateB implements State { @Override public void handle(String sampleParameter) { System.out.println("ConcreteStateB handle : " + sampleParameter); } }
Client class
public class Client { public static void main(String[] args){ //Create status State state = new ConcreteStateB(); //Create environment Context context = new Context(); //Set state to environment context.setState(state); //request context.request("test"); } }
As can be seen from the above, the behavior request() of the environment class Context is delegated to a specific State class. By using the polymorphism principle, the content of the attribute State of the environment class Context can be dynamically changed from pointing to one specific State class to pointing to another, so that the behavior request() of the environment class can be executed by different specific State classes.
Applicable scenario
(1) The behavior of an object depends on its state and can be changed at run time according to the state.
(2) The code contains a large number of conditional statements related to object State: an operation contains a large number of multi branch conditions (if else (or switch case) Statement, and these branches depend on the State of the object. This State is usually represented by one or more enumeration constants. Usually, multiple operations contain the same conditional structure. The State mode puts each conditional branch into a separate class. This allows you to treat the State of the object as an object according to the situation of the object itself, which can not depend on it Independent of other objects.
Voting cases
Consider the application of an online voting system. In order to control the same user to vote, if a user votes repeatedly and votes more than 5 times, it will be judged as malicious vote swiping, and the user's voting qualification will be cancelled. Of course, at the same time, his vote will also be cancelled; if a user votes more than 8 times, he will enter the blacklist, and it is prohibited to log in and make the user vote again Use the system.
To implement using the state mode, first define the various states of the voting process. According to the above description, it is roughly divided into four states: normal voting, repeated voting, malicious swiping and entering the blacklist. Then create a voting management object (equivalent to Context).
The structure diagram of the system is as follows:
Abstract state class
//Abstract state class public interface VoteState { /** * Behavior corresponding to processing status * @param user Voter * @param voteItem Voting items * @param voteManager The voting context is used to implement the function processing corresponding to the state, * Data that can be called back to the context */ public void vote(String user,String voteItem,VoteManager voteManager); }
Specific status class - normal voting
//Specific status - normal voting public class NormalVoteState implements VoteState { @Override public void vote(String user, String voteItem, VoteManager voteManager) { //Normal voting, recorded in the voting record voteManager.getMapVote().put(user, voteItem); System.out.println("Congratulations on the successful vote"); } }
Specific status class – repeat voting
//Specific status class -- repeated voting public class RepeatVoteState implements VoteState { @Override public void vote(String user, String voteItem, VoteManager voteManager) { //Repeat voting and do not deal with it for the time being System.out.println("Please do not vote again"); } }
Specific status class - malicious voting
//Malicious ticket swiping public class SpiteVoteState implements VoteState{ @Override public void vote(String user, String voteItem, VoteManager voteManager) { // Malicious voting, cancel the user's voting qualification and cancel the voting record String str = voteManager.getMapVote().get(user); if(str != null){ voteManager.getMapVote().remove(user); } System.out.println("You have malicious screen swiping behavior and are disqualified from voting"); } }
Specific status class - blacklist
//blacklist public class BlackVoteState implements VoteState { @Override public void vote(String user, String voteItem, VoteManager voteManager) { //Log in to the blacklist and prohibit logging in to the system System.out.println("If you enter the blacklist, you will be prohibited from logging in and using the system"); } }
Environment class
//Environment class public class VoteManager { //Maintain an abstract state object private VoteState state; //Record the results of user voting. Map < string, string > corresponds to map < user name, voting options > private Map<String,String> mapVote = new HashMap<String,String>(); //Record the number of user votes. Map < string, integer > corresponds to map < user name, number of votes > private Map<String,Integer> mapVoteCount = new HashMap<String,Integer>(); /** * Get the Map of user voting results */ public Map<String, String> getMapVote() { return mapVote; } /** * vote * @param user Voter * @param voteItem Voting options */ public void vote(String user,String voteItem){ //1. Increase the number of votes for the user //Retrieve the number of votes the user has cast from the record Integer oldVoteCount = mapVoteCount.get(user); if(oldVoteCount == null){ oldVoteCount = 0; } oldVoteCount += 1; mapVoteCount.put(user, oldVoteCount); //2. Judging the voting type of the user is equivalent to judging the corresponding status //Is it normal voting, repeated voting, malicious voting or blacklist status if(oldVoteCount == 1){ state = new NormalVoteState(); } else if(oldVoteCount > 1 && oldVoteCount < 5){ state = new RepeatVoteState(); } else if(oldVoteCount >= 5 && oldVoteCount <8){ state = new SpiteVoteState(); } else if(oldVoteCount > 8){ state = new BlackVoteState(); } //Then transfer the state object to perform the corresponding operation state.vote(user, voteItem, this); } }
Client test
public class Client { public static void main(String[] args) { VoteManager vm = new VoteManager(); for(int i=0;i<9;i++){ vm.vote("u1","A"); } } }
As can be seen from the above example, the state transition is basically an internal behavior, which is mainly maintained within the state mode. For example, for a voter, his operation is voting at any time, but the processing of the voting management object is not necessarily the same. The state will be judged according to the number of votes, and then different processing will be selected according to the state.
Cognitive state model
State and behavior
- The so-called object state usually refers to the value of the attribute of the object instance, while the behavior refers to the function of the object. More specifically, most of the behavior can correspond to the method.
- The function of state mode is to separate the behavior of States and call different functions corresponding to different states by maintaining the changes of states. That is, states and behaviors are related, and their relationship can be described as: state determines behavior.
- Since the state is changed during operation, the behavior will also change according to the change of state during operation.
Parallelism of behavior
Pay attention to parallel lines rather than equality. The so-called parallelism refers to that the behavior of each state is at the same level, independent and unrelated. It is determined which parallel line to follow according to different states. The behavior is different, of course, the corresponding implementation is also different and cannot be replaced with each other.
Equality emphasizes replaceability. We are different descriptions or implementations of the same behavior. Therefore, when the same behavior occurs, any implementation can be selected according to conditions for corresponding processing.
You may find that the structure of state mode is exactly the same as that of strategy mode, but their purpose, realization and essence are completely different. The characteristics between behaviors are also a very important difference between state mode and strategy mode. The behavior of state mode is parallel and cannot be replaced with each other; while the behavior of strategy mode is equal and replaceable To replace each other.
Environment and state processing objects
- In the state mode, the context is the object holding the state, but the context itself does not handle the behavior related to the state, but delegates the function of processing the state to the state processing class corresponding to the state.
- In a specific state processing class, it is often necessary to obtain the data of the environment (Context) itself, and even call back the method of the environment (Context) when necessary. Therefore, the environment (Context) itself is usually passed to the specific state processing class as a parameter.
- Generally, the client only interacts with the context. The client can configure a context with a state object. Once the configuration is completed, it no longer needs to deal with the state object. The client is usually not responsible for maintaining the state during operation, nor for deciding which specific state processing object to use later.
Advantages of state mode
- Each state is a subclass. As long as you add a state, you need to add a subclass. If you modify a state, you can modify only one subclass.
- The structure is clear, avoiding the use of too many switch... case or if... else statements, avoiding the complexity of the program and improving maintainability.
- State objects can be shared. If state objects have no instance variables - that is, the states they represent are completely encoded by their types - then each Context object can share a state object. When states are shared in this way, they must be lightweight objects with no internal state but only behavior.
Disadvantages of state mode
- The use of state mode will inevitably increase the number of system classes and objects.
- The structure and implementation of state mode are complex. If it is not used properly, it will lead to the confusion of program structure and code.
Comparison of status mode and policy mode
Similarities:
- In the state mode and policy mode, the Context object is closed for modification. Adding a new state or policy does not need to modify the Context.
- Just as the Context in the state mode will have an initial state, the policy mode also has a default policy.
- State patterns encapsulate different behaviors with different states, while policy patterns encapsulate different behaviors with different policies.
- They all rely on subclasses to implement related behaviors
Differences:
The most fundamental difference is that the strategy model is a variety of solutions to the same problem, and there is no correlation between these different solutions; The state mode is different. The state mode requires correlation between states in order to realize state transition.