介紹
- 一個(gè)對(duì)象有狀態(tài)變化
- 每次狀態(tài)變化都會(huì)觸發(fā)一個(gè)邏輯
- 不能總是用
if else
來(lái)控制
示例
- 交通信號(hào)燈不同顏色的變化
UML類(lèi)圖
-
傳統(tǒng)UML類(lèi)圖
-
簡(jiǎn)化后的UML類(lèi)圖
代碼演示
// 狀態(tài)(紅燈、綠燈、黃燈)
class State {
constructor(color) {
this.color = color;
}
// 設(shè)置狀態(tài)
handle(context) {
console.log(`turn to ${this.color} light`)
context.setState(this)
}
}
// 主體
class Context {
consructor() {
this.state = null
}
// 獲取狀態(tài)
getState() {
return this.state
}
setState(state) {
this.state = state
}
}
// test
let context = new Context()
let green = new State('green')
let yellow = new State('yellow')
let red = new State('red')
// 綠燈亮了
green.handle(context)
console.log(context.getState())
場(chǎng)景
有限狀態(tài)機(jī)
- 有限個(gè)狀態(tài)、以及在這些狀態(tài)之間的變化
- 如交通信號(hào)燈
- 使用開(kāi)源lib:javascript-state-machine
- github.com/jakesgordon/javascript-state-machine
有限狀態(tài)機(jī)- “收藏”和“取消”
// 狀態(tài)機(jī)模型
var fsm = new StateMachine({
init: '收藏', // 初始狀態(tài),待收藏
transitions: [
{
name: 'doStore',
from: '收藏',
to: '取消收藏'
},
{
name: 'deleteStore',
from: '取消收藏',
to: '收藏'
}
],
methods: {
// 執(zhí)行收藏
onDoStore: function () {
alert('收藏成功')
updateText()
},
// 取消收藏
onDeleteStore: function () {
alert('已取消收藏')
updateText()
}
}
})
var $btn = $('#btn')
// 點(diǎn)擊事件
$btn.click(function() {
if (fsm.is('收藏')) {
fsm.doStore()
} else {
fsm.deleteStore()
}
})
// 更新文案
function updateText() {
$btn.text(fsm.state)
}
// 初始化文案
updateText()
寫(xiě)一個(gè)簡(jiǎn)單的Promise
- 回顧Promise的語(yǔ)法
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 = '';
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就是一個(gè)有限狀態(tài)機(jī)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-727615.html
- Promise三種狀態(tài):pending fullfilled rejected
- pending -> fullfilled或者 pending -> rejected
- 不能逆向變化
-
寫(xiě)代碼文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-727615.html
// 模型
var fsm = new StateMachine({
init: 'pending',
transitions: [
{
name: 'resolve',
from: 'pending',
to: 'fullfilled'
},
{
name: 'reject',
from: 'pending',
to: 'rejected'
}
],
methods: {
// 成功
onResolve: function (state, data) {
// 參數(shù):state - 當(dāng)前狀態(tài)實(shí)例;data - fsm.resolve(xxx) 執(zhí)行時(shí)傳遞過(guò)來(lái)的參數(shù)
data.successList.forEach(fn => fn())
},
// 失敗
onReject: function (state, data) {
// 參數(shù): state - 當(dāng)前狀態(tài)實(shí)例;data - fsm.reject(xxx) 執(zhí)行時(shí)傳遞過(guò)來(lái)的參數(shù)
data.failList.forEach(fn => fn())
}
}
})
// 定義Promise
class MyPromise {
// fn 回調(diào)函數(shù)
constructor(fn) {
this.successList = []
this.failList = []
// 接收兩個(gè)函數(shù)參數(shù),第一個(gè)為resolve回調(diào),第二個(gè)為reject回調(diào)
fn(() => {
// resolve 函數(shù)
fsm.resolve(this) // fsm觸發(fā)onResolve函數(shù)
}, () => {
// reject 函數(shù)
fsm.reject(this) // fsm觸發(fā)onResolve函數(shù)
})
}
// then函數(shù),successFn failFn 不會(huì)立即執(zhí)行,放進(jìn)數(shù)組里
then(successFn, failFn) {
this.successList.push(successFn)
this.failList.push(failFn)
}
}
// 測(cè)試代碼
function loadImg(src) {
const promise = new MyPromise(function (resolve, reject) {
let img = document.createElement('img')
img.onload = function() {
resolve(img)
}
img.onerror = function() {
reject()
}
img.src = src
})
return promise
}
let src = 'https://imgxxx';
let result = loadImg(src)
result.then(function() {
console.log('ok1')
}, function() {
console.log('fail1')
})
result.then(function() {
console.log('ok2')
}, function() {
console.log('fail2')
})
設(shè)計(jì)原則驗(yàn)證
- 將狀態(tài)對(duì)象和主題對(duì)象分離,狀態(tài)的變化邏輯單獨(dú)處理
- 符合開(kāi)放封閉原則
到了這里,關(guān)于設(shè)計(jì)模式-狀態(tài)模式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!