国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

輕松掌握JavaScript狀態模式

2019-11-20 09:03:24
字體:
來源:轉載
供稿:網友

狀態模式 

狀態模式(State)允許一個對象在其內部狀態改變的時候改變它的行為,對象看起來似乎修改了它的類。 

狀態模式的使用場景也特別明確,有如下兩點:
 1.一個對象的行為取決于它的狀態,并且它必須在運行時刻根據狀態改變它的行為。(有些對象通常會有好幾個狀態,在每個狀態都只可以做當前狀態才可以做的事情,而不能做其它狀態能做的事兒)

 2.一個操作中含有大量的分支語句,而且這些分支語句依賴于該對象的狀態。狀態通常為一個或多個枚舉常量的表示。 

一、有限狀態機

 1.狀態總數(state)是有限的。
 2.任一時刻,只處在一種狀態之中。
 3.某種條件下,會從一種狀態轉變(transition)到另一種狀態。 

通用做法:將狀態封裝成獨立的類(狀態機),并將請求委托給當前的狀態對象,當對象的內部狀態發生改變時,會帶來不同的行為變化。 

二、性能優化點

 1.如何管理狀態對象的創建和銷毀?第一種僅當state對象被需要時才創建并隨后銷毀(state對象比較龐大,優先選擇), 另一種是一開始就創建好所有的狀態對象,并且始終不銷毀它們(狀態改變頻繁)。
 2.利用享元模式共享一個state對象。 

舉個稍微復雜的例子,相信大家都玩過角色扮演類游戲,里面的角色就有很多種狀態(站、走、跑、跳、蹲等),各個狀態之間的切換是被規定好了的,且任何時刻都只能處于一種狀態中,而在每個狀態下,角色只能做當前狀態下被允許的行為(如:普通攻擊、各種技能攻擊、防御等) 

這是我寫的移動小球的例子:

<!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.curentState = 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">按下方向鍵移動方塊 <div id="go"></div></div></body></html>

三、JavaScript版本的狀態機(以簡單的開關燈為例)

 1.通過Function.prototype.call方法直接把請求委托給某個字面量對象來執行

 // 狀態機var FSM = { off: { buttonWasPressed: function() {  console.log("關燈");  this.button.innerHTML = "下一次按我是開燈"; // 這是Light上的屬性!!!  this.currState = FSM.on;   // 這是Light上的屬性!!! } }, on: { buttonWasPressed: function() {  console.log("開燈");  this.button.innerHTML = "下一次按我是關燈";  this.currState = FSM.off; } },}; var Light = function() { this.currState = FSM.off; // 設置當前狀態 this.button = null;}; Light.prototype.init = function() { var button = document.createElement("button"); self = this;  button.innerHTML = "已關燈"; this.button = document.body.appendChild(button); this.button.onclick = function() { // 請求委托給FSM狀態機 self.currState.buttonWasPressed.call(self); } } var light = new Light();light.init(); 

2.利用delegate函數

 var delegate = function(client, delegation) { return { buttonWasPressed: function() {  return delegation.buttonWasPressed.apply(client, arguments); } };}; // 狀態機var FSM = { off: { buttonWasPressed: function() {  console.log("關燈");  this.button.innerHTML = "下一次按我是開燈";  this.currState = this.onState; } }, on: { buttonWasPressed: function() {  console.log("開燈");  this.button.innerHTML = "下一次按我是關燈";  this.currState = this.offState; } },}; var Light = function() { this.offState = delegate(this, FSM.off); this.onState = delegate(this, FSM.on); this.currState = this.offState; // 設置當前狀態 this.button = null;}; Light.prototype.init = function() { var button = document.createElement("button"); self = this;  button.innerHTML = "已關燈"; this.button = document.body.appendChild(button); this.button.onclick = function() { // 請求委托給FSM狀態機 self.currState.buttonWasPressed(); }} var light = new Light();light.init(); 

狀態模式和策略模式很像,它們都封裝了一系列的算法或行為,它們都有一個上下文對象來把請求委托給封裝類(策略類、狀態機),但它們的意圖不同:
 1.策略類的各個屬性之間是平等平行的,它們之間沒有任何聯系
 2.狀態機中的各個狀態之間存在相互切換,且是被規定好了的。

參考文獻:JavaScript模式》 《JavaScript設計模式與開發實踐

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 阜城县| 北碚区| 黄浦区| 西安市| 宜君县| 惠水县| 漳平市| 财经| 荥经县| 长寿区| 双牌县| 邳州市| 仁怀市| 丰都县| 祁连县| 金堂县| 苗栗市| 正镶白旗| 项城市| 长汀县| 乌兰县| 浦县| 婺源县| 漾濞| 德阳市| 天柱县| 广西| 德安县| 孟村| 全椒县| 友谊县| 仲巴县| 富川| 武定县| 赞皇县| 大竹县| 罗城| 怀安县| 闽清县| 东平县| 大邑县|