(十二)状态模式
狀態模式
- 狀態模式
- 狀態模式 介紹
- 概念
- 示例
- 狀態模式 演示
- 狀態模式 場景
- 有限狀態機(finite state machine)
- 實現一個簡單的 Promise
- 狀態模式 總結
狀態模式
- 介紹
- 演示
- 場景
- 總結
狀態模式 介紹
- 一個對象有狀態變化
- 每次狀態變化都會觸發一個邏輯
- 不能總是用if…else來控制
概念
一個對象或者實例可能會有不同狀態的變化(例如交通信號燈),如果僅用if...else去處理狀態變化,擴展性非常差,特別是針對復雜的狀態變化。狀態模式就提出了一種處理復雜狀態變化且擴展性好的設計思路。
示例
- 交通信號燈不同顏色的變化
-
狀態模式 演示
傳統的 UML 類圖
簡化之后的 UML 類圖
代碼演示
class State {constructor(color) {this.color = color}handle(context) {console.log(`turn to ${this.color} light`)context.setState(this)} }class Context {constructor() {this.state = null}setState(state) {this.state = state}getState() {return this.state} }// 測試代碼 let context = new Context()let greed = new State('greed') let yellow = new State('yellow') let red = new State('red')// 綠燈亮了 greed.handle(context) console.log(context.getState()) // 黃燈亮了 yellow.handle(context) console.log(context.getState()) // 紅燈亮了 red.handle(context) console.log(context.getState())狀態模式 場景
有限狀態機(finite state machine)
- 有限個狀態
- 以及在這些狀態之間的變化 如交通信號燈
- 使用開源lib:javascript-state-machine
表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型,例如上一節的交通信號燈的狀態變化。
有一個開源 lib javascript-state-machine 實現了有限狀態機的功能。我們使用它來模擬一個比較常用的操作,“收藏”和“取消收藏”
// 狀態機模型 var fsm = new StateMachine({init: '收藏', // 初始狀態,待收藏transitions: [{name: 'doStore',from: '收藏',to: '取消收藏'},{name: 'deleteStore',from: '取消收藏',to: '收藏'}],methods: {// 執行收藏onDoStore: function () {alert('收藏成功')updateText()},// 取消收藏onDeleteStore: function () {alert('已取消收藏')updateText()}} })var $btn = $('#btn')// 點擊事件 $btn.click(function () {if (fsm.is('收藏')) {fsm.doStore()} else {fsm.deleteStore()} })// 更新文案 function updateText() {$btn.text(fsm.state) }// 初始化文案 updateText()實現一個簡單的 Promise
先回歸一下 Promise 的語法
function loadImg(src) {const promise = new Promise(function (resolve, reject) {var img = document.createElement('img')img.onload = function () {resolve(img)}img.onerror = function () {reject()}img.src = src})return promise }var src = 'http://www.imooc.com/static/img/index/logo_new.png' var result = loadImg(src)result.then(function (img) {console.log('success 1') }, function () {console.log('failed 1') }) result.then(function (img) {console.log('success 2') }, function () {console.log('failed 2') })Promise 就是一個有限狀態機,有三個狀態pending fullfilled rejected,其中的變化必須是pending -> fullfilled 或者pending -> rejected,不能逆向變化,這樣就可以根據有限狀態即實現一個基本的 Promise
// 模型 var fsm = new StateMachine({init: 'pending',transitions: [{name: 'resolve',from: 'pending',to: 'fullfilled'},{name: 'reject',from: 'pending',to: 'rejected'}],methods: {// 成功onResolve: function (state, data) {// 參數:state - 當前狀態示例; data - fsm.resolve(xxx) 執行時傳遞過來的參數data.successList.forEach(fn => fn())},// 失敗onReject: function (state, data) {// 參數:state - 當前狀態示例; data - fsm.reject(xxx) 執行時傳遞過來的參數data.failList.forEach(fn => fn())}} })// 定義 Promise class MyPromise {constructor(fn) {this.successList = []this.failList = []fn(() => {// resolve 函數fsm.resolve(this)}, () => {// reject 函數fsm.reject(this)})}then(successFn, failFn) {this.successList.push(successFn)this.failList.push(failFn)} }然后測試一下
// 測試代碼 function loadImg(src) {const promise = new MyPromise(function (resolve, reject) {var img = document.createElement('img')img.onload = function () {resolve(img)}img.onerror = function () {reject()}img.src = src})return promise } var src = 'http://www.imooc.com/static/img/index/logo_new.png' var result = loadImg(src) console.log(result)result.then(function (img) {console.log('success 1') }, function () { console.log('failed 1') }) result.then(function (img) {console.log('success 2') }, function () { console.log('failed 2') })注意,本節以講解狀態模式位置,僅實現了簡單的 Promise 原型,Promise 其他高級功能大家可自行去擴展
狀態模式 總結
- 狀態模式是什么
- 主要解決什么問題
- 核心:不同狀態變化的邏輯,分離實現,而不是用if...else放在一起判斷
- 有限狀態機
和觀察者模式的對比:兩者之間沒有矛盾,而是狀態模式中可以使用觀察者模式。
- 狀態模式:不同狀態的變化帶來的改變。類似于多種if..else的邏輯。
- 觀察者模式:先訂閱、后發布,觸發訂閱。類似于一次性觸發多個事件,并沒有if...else的判斷。
設計原則驗證:
- 將狀態對象和主題對象分離,狀態的變化邏輯單獨處理
- 符合開放封閉原則
總結
- 上一篇: 闲鱼网站二手市场(闲鱼二手市场家具)
- 下一篇: (十三)其他设计模式