“This is the 25th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

introduce

Many companies require as few if-else conditional branches as possible. You might want to use state patterns. I’ll talk to you about state patterns in this installment. If you know about game development games, you will often use finite state machines when developing game character states, which is a case of state mode.

For example, when we were kids, there was an old-fashioned fan on a hot summer day. It had three gears. The first press would turn the fan on, and the second press would turn it on, and the second press would turn it on, and the third press would turn the fan off. If we write the logic of the fan in code, we will frequently use if-else conditional branch statements. As the number of conditions increases, it will become more and more difficult for us to maintain and consult. Next, we will use the state mode to solve this problem in the case.

concept

The state pattern is a behavioral pattern. It solves the problem that the behavior of an object depends on its state and can change its related behavior as its state changes.

case

var FSM = {
	off: {name:"Closed".action:function(){
			console.log("Trigger button, current status by"+this.currState.name+"Change to a first class wind.");
		},
		change:function(){
			this.currState = this.state.lv1;
			return 'Open first class wind speed'}},lv1: {name:"Turn on wind speed one".action:function(){
			console.log("Trigger button, current status by"+this.currState.name+"Change to a category two wind.");
		},
		change:function(){
			this.currState = this.state.lv2;
			return 'Open second wind speed'}},lv2: {name:"Open second wind".action:function(){
			console.log("Trigger button, current status by"+this.currState.name+"Change to a category three wind.");
		},
		change:function(){
			this.currState = this.state.lv3;
			return 'Force three'}},lv3: {name:"Force three wind".action:function(){
			console.log("Trigger button, current status by"+this.currState.name+"Make changes to close");
		},
		change:function(){
			this.currState = this.state.off;
			return 'off'}}}var delegate = function(client,delegation){
	return {
		name: delegation.name,
		change:function(){
			return delegation.change.apply(client,arguments);
		},
		action:function(){
			return delegation.action.apply(client,arguments); }}}var Fan = function(){
	this.state = {
		off:delegate(this,FSM.off),
		lv1:delegate(this,FSM.lv1),
		lv2:delegate(this,FSM.lv2),
	    lv3:delegate(this,FSM.lv3)
	}
	this.currState = this.state.off;
}
Fan.prototype.setCurrState = function(stateName){
	this.currState = this.state[stateName] || this.state.off;
	return this;
}
Fan.prototype.init = function(){
	var btn = document.createElement("button");
	var msg = document.createElement("span");
	msg.style.marginLeft = "15px";
	btn.innerHTML = "Fan button";
	msg.innerHTML = "State:"+ this.currState.name;
	btn.addEventListener("click".function(e){
		this.currState.action.apply(this);
		var ret = this.currState.change.apply(this);
		msg.innerHTML = "State:"+ret;
	}.bind(this),false);
	document.body.appendChild(btn);
	document.body.appendChild(msg);
}
Copy the code

Here we write several states in an FSM object, including the name of the state, the behavior, and the new state to change.

Let them manage them in a unified way through a delegate for convenience.

The state of a Fan class is the given state, and setCurrState can be set directly. Init as an initializer, for the sake of creating the DOM directly in JS.

Next, we instantiate the Fan class, initially set to closed.

var fan = new Fan();
fan.setCurrState("off").init();
Copy the code

Now is the time to witness the miracle

So we can use it to replace the ugly if-else, and we’ll see how many states we can add.

advantages

  1. Encapsulate transition rules, making them clearer, and allow state transition logic to be integrated with state objects, rather than some giant conditional block, increasing maintainability.
  2. Put all the behavior associated with a state into a single class, and you can easily add new states by simply changing the object’s state to change its behavior.
  3. You can reduce the number of objects in the system by having multiple environment objects share a single state object.

disadvantages

  1. The use of state patterns inevitably increases the number of system classes and objects.
  2. The structure and implementation of state pattern are complicated, and it will lead to confusion of program structure and code if used improperly.
  3. State modes do not support the “on/off principle” very well. For state modes that can be switched, adding a new state class requires modifying the source code responsible for the transition to the new state, and modifying the behavior of a state class requires modifying the source code of the corresponding class.

Usage scenarios

  1. A situation in which behavior changes as the state changes
  2. Logic that replaces conditional branch statements.

conclusion

The key of state mode is to distinguish the internal state of things. The change of internal state of things often brings about the change of behavior of things. It makes a lot of your messy code clearer.