亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

FSM狀態(tài)機之狀態(tài)模式

k00baa / 452人閱讀

摘要:要注意這里的一個狀態(tài)行為因為這個詞是狀態(tài)模式中最重要的個概念??紤]到這點,聰明的在中推出了狀態(tài)機這個偽函數(shù),能夠幫助我們快速實現(xiàn)狀態(tài)化。這里就引入了狀態(tài)機這個概念,以及和他對應(yīng)的狀態(tài)表。

?首先聲明一點,這個模式是我目前見過最好用(本人觀點),但是也是最難理解的一個(本人觀點)。 所以大家需要做好心理準備,如果,對這個模式?jīng)]有特別強烈的需求,比如: 我有一個Button,我按次數(shù)點擊它,他會觸發(fā)不同的狀態(tài) 等等這樣的,可以學習一下其他的模式。但是!!! 如果你看了我這篇文章,被我前面說的話嚇到了,那么就繼續(xù)往下看,其實,狀態(tài)模式是最好用,也是最容易掌握的一個。

大話狀態(tài)模式

上面已經(jīng)提到了,狀態(tài)模式其實就是,一個事物的內(nèi)部狀態(tài)的改變,產(chǎn)生不同的行為。 要注意這里的

"一個","狀態(tài)","行為". 因為這3個詞是狀態(tài)模式中最重要的3個概念。

同樣,舉個栗子

大家家里都有空調(diào)吧,remoter應(yīng)該都用過。 首先我們拿一個簡單的使喚。 就拿 on/off 鍵吧。首先,遙控器會記錄當前的狀態(tài)(假設(shè)他會這樣),如果是on, 當你點擊 他會發(fā)出off的信號,如果你是off,則會發(fā)出on的信號.我們用程序說明一下.

var switches = (function(){
    var state = "off";
    return function(){
        if(state === "off"){
            console.log("打開空調(diào)");
            state = "on";
        }else if(state === "on"){
            console.log("關(guān)閉空調(diào)");
            state = "off";
        }
    }
})();
document.querySelector(".switch").addEventListener("click",function(){
    switches();  //模仿你打開/關(guān)閉空調(diào)的狀態(tài)
},false)

很簡單吧,一個閉包+一個變量 就可以構(gòu)成一個 狀態(tài)機,是不是超級神奇呢?
恩,看到這里,聰明的人會,會心一笑,然后繼續(xù)往下看。
是個屁。
想想,如果空調(diào)開關(guān)要是都只有兩種狀態(tài),尼瑪誰用啊!!!
滿是turn on/off. 就跟寫2進制一樣。實話說,哥匯編學的差,所以也十分不愿意直視二進制,你讓我使喚開關(guān)跟寫匯編似的,操。 0001是開,0000是關(guān),0010是加熱模式,0011是制冷模式。

所以,海爾,美的考慮到國情,制造了比較人性化的remoter。
現(xiàn)在,如果我們使用上面那種模式來寫,切換模式的switch。

var switches = (function(){  //auto->hot->cold->wind->dry->auto
    var state = "auto";
    return function(){
        if(state === "auto"){
            console.log("制熱");
            state = "hot";
        }else if(state === "hot"){
            console.log("制冷");
            state = "cold";
        }else if(state === "cold"){
            console.log("送風");
            state = "wind";
        }else if(state === "wind"){
            console.log("除濕");
            state = "dry";
        }else if(state === "dry"){
            console.log("自動");
            state = "auto";
        }
    }
})();
document.querySelector(".switch").addEventListener("click",function(){
    switches();  //模仿你切換空調(diào)的模式
},false);

呵呵呵~ 功能是實現(xiàn)了,不過代碼,又被if語句給rape的。 性能的強奸犯,閱讀的殺手 恐怕就算if語句了. 所以,為了不犯罪,我們需要優(yōu)化我們的狀態(tài)模式。

高級狀態(tài)模式

其實,這個狀態(tài)模式的寫法和命令模式有著異曲同工的妙處。即,中間有個狀態(tài)倉庫,然后分別將命令轉(zhuǎn)發(fā)給對應(yīng)的執(zhí)行類。
總結(jié)一下。 高級狀態(tài)模式需要有,狀態(tài)倉庫,狀態(tài)類,狀態(tài)執(zhí)行者,這3個要點。 對應(yīng)著我們的,”一個“,"狀態(tài)","行為". 一個倉庫,不同的狀態(tài),不同的執(zhí)行。
just do it.

//定義狀態(tài)
var Auto= function(button){
    this.turn = button;
}
Auto.prototype.press= function(){
    console.log("制熱");
    this.turn.setState("hot");
}
var Hot = function(button){
    this.turn = button;
}
Hot.prototype.press= function(){
    console.log("制冷");
    this.turn.setState("cold");
}
var Cold = function(button){
    this.turn = button;
}
Cold.prototype.press= function(){
    console.log("送風");
    this.turn.setState("wind");
}
var Wind = function(button){
    this.turn = button;
}
Wind.prototype.press= function(){
    console.log("除濕");
    this.turn.setState("dry");
}
var Dry = function(button){
    this.turn = button;
}
Dry.prototype.press= function(){
    console.log("自動");
    this.turn.setState("auto");
}
//定義狀態(tài)倉庫
var Remoter = function(){
    this.auto = new Auto(this);
    this.hot = new Hot(this);
    this.cold = new Cold(this);
    this.wind = new Wind(this);
    this.dry = new Dry(this);
    this.state = "auto";
}
Remoter.prototype.setState = function(state){
    this.state=state;
}
Remoter.prototype.press = function(){
    this[this.state].press();  //執(zhí)行對應(yīng)狀態(tài)的press
}
Remoter.prototype.init = function(){  //定義執(zhí)行者
    document.querySelector(".switch").addEventListener("click",()=>{
        this.press();
    },false);
}
new Remoter.init();  //初始化

上面那種就是一個比較模式化的寫法,而且,可復用,可添加。 比上面那種的逼格不知道高到哪里去,但是,實現(xiàn)成本也是挺大的??紤]到這點,聰明的ECMA-262在es6中推出了狀態(tài)機這個偽函數(shù),能夠幫助我們快速實現(xiàn)狀態(tài)化。
Duang~
就是generator函數(shù)。 目前FF,edge,chrome 最新版本已經(jīng)支持。不過可以使用babel進行轉(zhuǎn)化.
我們使用generator進行重構(gòu).
我比較懶,我們就先實現(xiàn)前3個模式的轉(zhuǎn)化吧。

var auto = function(){
    console.log("自動");
}
var hot = function(){
    console.log("制熱");
}
var cold = function(){
    console.log("制冷");
}
function* models(){
    for(var i = 0,fn,len=arguments.length;fn = arguments[i++];){
        yield fn();
        if(i===len){
            i = 0;
        }
    }
}
var exe = models(auto,hot,cold);  //按照模式順序排放
document.querySelector(".switch").addEventListener("click",function(){
    exe.next();
},false);

已經(jīng)沒有了if來進行分支判斷,效果也是蠻不錯的。 關(guān)于generator的用法,還有進程控制,這些都是比較高級的用法,有興趣的同學可以參考 阮老師的 es6講解. 但是,推薦還是使用,一個倉庫,不同狀態(tài),不同行為,這樣函數(shù)對象式的寫法,擴展性比較強。主要原因是因為,generator還未普及,以及設(shè)置他進程的順序比較復雜。不過,平常本人喜歡裝裝逼,永遠熱愛新技術(shù),所以大部分時候還是會使用generator。 總之,程序員并不是程序員,我們要有自己的核心價值觀,找到自己最對的 "瑪卡瑞納",這才是我們程序員應(yīng)該有的情懷。
我們仔細觀察一下上面使用"類"寫出來的狀態(tài)模式,會發(fā)現(xiàn),狀態(tài)類是不是感覺可以使用享元模式優(yōu)化呢?沒錯。因為他的方法和狀態(tài)都是一致的,當然可以使用。

var obj = {
    auto(){
        console.log("自動")
        return "hot";
    },
    hot(){
        console.log("制熱");
        return "cold";
    },
    cold(){
        console.log("制冷");
        return "auto"
    }
}
var State = function(){
    this.state = "auto";
    this.obj = obj;
}
State.prototype.next = function(){
    this.state = this.obj[this.state]()
}
new State().next();  //測試通過.

這只是一種比較輕巧的方法,js,最出名的就是他的動態(tài),無拘無束,你可以天馬行空的寫出你的代碼(但是,必須保證的你代碼不會變成 鳳姐 ).
但從上面的代碼可以看出,如果程序里面使用return 的話,很容易會造成你函數(shù)的邏輯復雜度,所以我們這里推薦使用一個state進行保存,將this.state傳入。 當然,我們并不是當參數(shù)參入了(太low),我們使用委托的技術(shù)傳入,相當于給this動態(tài)織入一個函數(shù)。這個方法就叫: apply和call. 哈哈,是不是有種感覺(怎么又是你).

var obj = {
    auto(){
        console.log("自動")
        this.state = "hot";
    },
    hot(){
        console.log("制熱");
        this.state = "cold";
    },
    cold(){
        console.log("制冷");
        this.state = "auto";
    }
}
var State = function(){
    this.state = "auto";
    this.obj = obj;
}
State.prototype.next = function(){
    this.obj[this.state].call(this);
}
new State().next();

沒錯,這下,我們不僅能將函數(shù)動態(tài)織入,而且可以直接改動state,這樣可以給自己程序的擴展性加上一分。
當然,狀態(tài)模式的寫法還有很多,比如delegate函數(shù)的寫法等等。 不過,找到自己的"瑪卡瑞納"才是最棒的。
上面只是一個線上的流式狀態(tài)切換,并沒有涉及很復雜的業(yè)務(wù)邏輯。但是,如果你在開發(fā)一個大型項目的時候,涉及的狀態(tài)可謂是五花八門,還是以空調(diào)遙控器為例,比如,你切換到模式選擇的時候,你的上下左右鍵,只能控制模式的切換,而不能控制風速大小,當你切換到風速選擇模式的時候,同樣不能控制其他的功能。 所以,如果按照上面那種 單線式的狀態(tài)切換是不夠的。 這里就引入了FsM(finite-state-machine),狀態(tài)機這個概念,以及和他對應(yīng)的狀態(tài)表。
如下圖

如果你是學機械的,那么這個狀態(tài)切換的概念應(yīng)該非常熟悉,在CH40161(一種自觸發(fā)式芯片)中,你輸入一個觸發(fā)信號,他可以按照你這個觸發(fā)信號逐步觸發(fā)(我機械太渣,但意外的喜歡上計院). 在js中,gordon大神(有8個contributor)已經(jīng)寫出了這個狀態(tài)庫。有興趣的同學可以看一看。
傳送門: FSM。
其實,他里面最重要的就是"狀態(tài)"和"狀態(tài)切換"的規(guī)則。
先看一個demo:

var fsm = StateMachine.create({
  initial: "green",
  events: [
    { name: "warn",  from: "green",  to: "yellow" },
    { name: "panic", from: "yellow", to: "red"    },
    { name: "calm",  from: "red",    to: "yellow" },
    { name: "clear", from: "yellow", to: "green"  }
  ],
  callbacks: {
    onpanic:  function(event, from, to, msg) { alert("panic! " + msg);               },
    onclear:  function(event, from, to, msg) { alert("thanks to " + msg);            },
    ongreen:  function(event, from, to)      { document.body.className = "green";    },
    onyellow: function(event, from, to)      { document.body.className = "yellow";   },
    onred:    function(event, from, to)      { document.body.className = "red";      },
  }
});

這已經(jīng)定義好了一個完整的單線式,狀態(tài)切換隊列。
當你觸發(fā)fsm.warn(); 狀態(tài)就是從green->yellow。
當你觸發(fā)fsm.panic(); 狀態(tài)就是從yellow->red.
...
說一下基本用法
events 里面就是你定義的狀態(tài)表的規(guī)則

name: 標識,狀態(tài)切換的函數(shù)名
from: 標識 為切換之前的狀態(tài)
to: 標識 為切換之后的狀態(tài)

callbacks 里面就是對狀態(tài)和切換規(guī)則函數(shù)的定義. 這里不說的太復雜,就按照基本的講解吧。

使用on+Name; 定義狀態(tài)切換的函數(shù)
使用on+State: 定義某個狀態(tài)時觸發(fā)的函數(shù)

當然,還有

onbeforeevent - fired before any event
onleavestate - fired when leaving any state
onenterstate - fired when entering any state
onafterevent - fired after any event

這些比較細,這里就不做詳細介紹,如果有興趣的同學可以去github上面看一看,理解起來也不是很難。我這里介紹的我經(jīng)常使用的。
所以,上面的流程就是。
使用fsm.panic() 之后。
觸發(fā)順序為: onpanic()->red();
如果你狀態(tài)不對,而強行調(diào)用fsm.panic的話就會觸發(fā)error函數(shù)(這里沒有寫). 所以,上面寫的fsm 差不多已經(jīng)夠用了,關(guān)鍵看你如果組合了。 要知道,二維難度 >> 一維難度。 有一個好工具,能把你的工作量降到最低。

談?wù)劆顟B(tài)模式

說到這里,我的這篇blog大部分是介紹 一些基本原理和方法,狀態(tài)模式的應(yīng)用在程序設(shè)計中是非常重要的一個概念,如果你掌握了,語言只會變?yōu)槟愕囊粋€工具,因為 你已經(jīng)吃透了 隱藏在 語言背后的 secret. 最后還是那句話, 不要為了模式而模式,但狀態(tài)模式確實是個好模式。
ending~.

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/78547.html

相關(guān)文章

  • 設(shè)計模式手冊之狀態(tài)模式

    摘要:什么是狀態(tài)模式狀態(tài)模式對象行為是基于狀態(tài)來改變的。原文地址設(shè)計模式手冊之狀態(tài)模式優(yōu)缺點優(yōu)點封裝了轉(zhuǎn)化規(guī)則,對于大量分支語句,可以考慮使用狀態(tài)類進一步封裝。 1. 什么是狀態(tài)模式? 狀態(tài)模式:對象行為是基于狀態(tài)來改變的。 內(nèi)部的狀態(tài)轉(zhuǎn)化,導致了行為表現(xiàn)形式不同。所以,用戶在外面看起來,好像是修改了行為。 Webpack4系列教程(17篇) + 設(shè)計模式手冊(16篇):GitHub地址 博...

    call_me_R 評論0 收藏0
  • 設(shè)計模式手冊之狀態(tài)模式

    摘要:什么是狀態(tài)模式狀態(tài)模式對象行為是基于狀態(tài)來改變的。原文地址設(shè)計模式手冊之狀態(tài)模式優(yōu)缺點優(yōu)點封裝了轉(zhuǎn)化規(guī)則,對于大量分支語句,可以考慮使用狀態(tài)類進一步封裝。 1. 什么是狀態(tài)模式? 狀態(tài)模式:對象行為是基于狀態(tài)來改變的。 內(nèi)部的狀態(tài)轉(zhuǎn)化,導致了行為表現(xiàn)形式不同。所以,用戶在外面看起來,好像是修改了行為。 Webpack4系列教程(17篇) + 設(shè)計模式手冊(16篇):GitHub地址 博...

    Faremax 評論0 收藏0
  • 使用有限狀態(tài)機管理狀態(tài)

    摘要:集成到去使用如果想在中使用,想到比較方便的使用形式是高階組件,需要用到有限狀態(tài)機的組件傳進高階組件,就立馬擁有了使用有限狀態(tài)機的能力。 背景 近年來由于一些前端框架的興起而后逐漸成熟,組件化的概念已經(jīng)深入人心,為了管理好大型應(yīng)用中錯綜復雜的組件,又有了單向數(shù)據(jù)流的思想指引著我們,Vuex、Redux、MobX等狀態(tài)管理工具也許大家都信手拈來。我們手握著這些工具,不斷思考著哪些數(shù)據(jù)應(yīng)該放...

    hiyang 評論0 收藏0
  • JavaScript 設(shè)計模式 一些筆記

    摘要:如果非要重寫父類的方法,比較通用的做法是原來的父類和子類都繼承一個更通俗的基類,原有的繼承關(guān)系去掉,采用依賴聚合,組合等關(guān)系代替。里氏替換原則通俗的來講就是子類可以擴展父類的功能,但不能改變父類原有的功能。一有限狀態(tài)機狀態(tài)總數(shù)是有限的。 設(shè)計模式 抽象類 抽象類的表現(xiàn) 不能被實例,只能被繼承 最少有一個抽象方法(多態(tài)的具體體現(xiàn)) // 汽車抽象類,當使用其實例對象的方法時會拋出錯誤...

    paulli3 評論0 收藏0
  • 游戲人工智能 讀書筆記 (四) AI算法簡介——Ad-Hoc 行為編程

    摘要:原文鏈接本文內(nèi)容包含以下章節(jié)本書英文版這個章節(jié)主要討論了在游戲中經(jīng)常用到的一些基礎(chǔ)的人工智能算法。行為樹是把的圖轉(zhuǎn)變成為一顆樹結(jié)構(gòu)。根據(jù)當前游戲的環(huán)境狀態(tài)得到某一個行為的效用值。 作者:蘇博覽商業(yè)轉(zhuǎn)載請聯(lián)系騰訊WeTest獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。原文鏈接:https://wetest.qq.com/lab/view/427.html 本文內(nèi)容包含以下章節(jié): Chapter 2 ...

    xinhaip 評論0 收藏0

發(fā)表評論

0條評論

k00baa

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<