Status Mode
State mode allows an object to change its behavior when its internal state changes, and the object appears to modify its class.
The usage scenarios of the status mode are also particularly clear, with the following two points:
1. The behavior of an object depends on its state, and it must change its behavior according to its state at run time. (Some objects usually have several states, in each state, you can only do what the current state can do, but not what other states can do)
2. An operation contains a large number of branch statements, and these branch statements depend on the state of the object. The state is usually a representation of one or more enumeration constants.
1. Finite state machine
1. The total number of states (state) is limited.
2. At any moment, you are only in one state.
3. Under certain conditions, it will transition from one state to another.
Common practice: encapsulate the state into an independent class (state machine) and delegate the request to the current state object. When the internal state of the object changes, it will cause different behavior changes.
2. Performance optimization points
1. How to manage the creation and destruction of state objects? The first is to create and then destroy the state objects only when they are needed (state objects are huge, preferred), and the other is to create all state objects from the beginning and never destroy them (state changes frequently).
2. Use the Enjoy Yuan mode to share a state object.
To give a slightly complex example, I believe everyone has played role-playing games, and the characters in it have many states (station, walking, running, jumping, squatting, etc.). The switching between various states is specified, and they can only be in one state at any time. In each state, the characters can only perform allowed behaviors in the current state (such as: ordinary attacks, various skill attacks, defenses, etc.)
Here is an example of the moving ball I wrote:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title></title> <script> window.onload = function() { var FSM = { show1: { clickBtn: function (key) { change.call(this,key); } }, show2: { clickBtn: function (key) { change.call(this,key); } }, show3: { clickBtn: function (key) { change.call(this,key); } }, show4: { clickBtn: function (key) { change.call(this,key); } } } }; var Ball = function () { this.curentState = FSM.show1; this.div = null; }; Ball.prototype.init = function () { var self = this; this.div = document.getElementById('go'); document.body.onkeydown = function (event) { var key = event.keyCode; self.curentState.clickBtn.call(self,key); } }; function change(key){ var styles = window.getComputedStyle(this.div), parentStyles = window.getComputedStyle(this.div.parentNode), top = parseInt(styles.top), left = parseInt(styles.left); if(key === 40){ top += (top+parseInt(styles.height))<parseInt(parentStyles.height) ? 10 : 0; this.div.style.top = top+'px'; this.currentState = FSM.show3; } if(key === 38){ top -= (top > 0 ? 10 : 0); this.div.style.top = top+'px'; this.curentState = FSM.show4; } if(key === 37){ left -= (left > 0 ? 10 : 0); this.div.style.left = left+'px'; this.curentState = FSM.show1; } if(key === 39){ this.curentState = FSM.show2; left += (left+parseInt(styles.width))<parseInt(parentStyles.width) ? 10: 0; this.div.style.left = left+'px'; } } var a = new Ball(); a.init(); } </script> <style> #div{ position: absolute; width: 80%; height: 80%; top: 0; bottom: 0; left: 0; right: 0; margin: auto; border: 1px solid darkcyan; } #go{ position:absolute; width:50px; height:50px; left: 10px; top:20px; border:1px solid gray; -webkit-border-radius : 50px; -moz-border-radius: 50px; border-radius: 50px; background-image: radial-gradient(circle, white 5%, black 100%); } </style></head><body><div id="div">Press the arrow key to move the square<div id="go"></div></div></body></html>3. JavaScript version of state machine (taking simple switch lights as an example)
1. Directly delegate the request to a literal object through the Function.prototype.call method to execute
// State machine var FSM = { off: { buttonWasPressed: function() { console.log("Downlight"); this.button.innerHTML = "Next pressing I'm turning on the light"; // This is a property on Light! ! ! this.currState = FSM.on; // This is the property on Light! ! ! } }, on: { buttonWasPressed: function() { console.log("Light on"); this.button.innerHTML = "Next pressing I'm turning off the light"; this.currState = FSM.off; } },}; var Light = function() { this.currState = FSM.off; // Set the current state this.button = null;}; Light.prototype.init = function() { var button = document.createElement("button"); self = this; button.innerHTML = "Light off"; this.button = document.body.appendChild(button); this.button.onclick = function() { // Request to delegate to the FSM state machine self.currState.buttonWasPressed.call(self); } } var light = new Light();light.init();2.Use the delegate function
var delegate = function(client, delegation) { return { buttonWasPressed: function() { return delegation.buttonWasPressed.apply(client, arguments); } };}; // State machine var FSM = { off: { buttonWasPressed: function() { console.log("Off"); this.button.innerHTML = "Next pressing I'm turning on the light"; this.currState = this.onState; } }, on: { buttonWasPressed: function() { console.log("On the light"); this.button.innerHTML = "Next pressing, I'm turning off the lights"; this.currState = this.offState; } },}; var Light = function() { this.offState = delegate(this, FSM.off); this.onState = delegate(this, FSM.on); this.currState = this.offState; // Set the current state this.button = null;}; Light.prototype.init = function() { var button = document.createElement("button"); self = this; button.innerHTML = "Light off"; this.button = document.body.appendChild(button); this.button.onclick = function() { // Request to delegate to the FSM state machine self.currState.buttonWasPressed(); }} var light = new Light(); light.init();State modes and policy modes are very similar. They both encapsulate a series of algorithms or behaviors. They all have a context object to delegate requests to encapsulated classes (policy classes, state machines), but their intentions are different:
1. The various attributes of the policy class are equally parallel, and there is no connection between them.
2. There is mutual switching between the various states in the state machine and it is specified.
References: "JavaScript Pattern" "JavaScript Design Pattern and Development Practice"
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.