状态模式
1. 介绍
- 一个对象有状态变化
- 每次状态变化都会触发一个逻辑
- 不能总是用 if…else 来控制
2. UML 演示
3. 代码演示
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
}
//获取状态
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())
//红灯亮
red.handle(context)
console.log(context.getState())
//黄灯亮
yellow.handle(context)
console.log(context.getState())
4. 场景
4.1 有限状态机
-
有限个状态、以及在这些状态之间的变化
-
交通灯
-
开源 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()
4.2 写一个简单的 Promise
- 是一个类
- 需要传一个函数
- 需要接受
resolve
,reject
这两个参数 - 返回 then 方法,接受两个参数
- 三种状态
pending
、fullfilled
、rejected
pending
->fullfilled
或者pending
->rejected
,不能逆向变
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)
}
}
//状态机
var StateMachine = require('javascript-state-machine')
var fsm = new StateMachine({
inti: 'pending',
transitions: [
{
name: 'resolve',
form: 'pending',
to: 'fullfilled'
},
{
name: 'reject',
form: '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())
}
}
})
//测试代码
function loadImg(src) {
let promise = new Promise(function(resolve, reject) {
let img = document.createElement('img')
img.onload = function() {
resolve(img)
}
img.onerror = function() {
reject('图片加载失败')
}
img.src = src
})
return promise
}
let src = '//img.mukewang.com/5bc45ce20001976409360316.jpg'
let result = loadImg(src)
result.then(
function(img) {
console.log('ok1')
},
function() {
console.log('fail1')
}
)
result.then(
function(img) {
console.log('ok2')
},
function() {
console.log('fail2')
}
)
5. 设计原则
- 将状态对象和主题对象分离,状态的变化逻辑单独处理
- 符合开放封闭原则