15 状态模式 – 前端设计模式系列教程

介绍
  • 一个对象有状态变化
  • 每次状态变化都会触发一个逻辑
  • 不能总是用if…else来控制
示例
交通信号灯不同的颜色变化
代码
// 状态类(模型)
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
    }
}

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())
yellow.handle(context)
console.log(context.getState())
red.handle(context)
console.log(context.getState())

 

场景
有限状态机
对比之前写的示例代码,这段代码左边的部分就相当于state,右边的相当于context
写个简单的Promise
利用StateMachine这个状态机插件写一个myPromise, StateMachine的语法先看一下官方文档。
Promise的主要原理就是监听3个状态然后来触发对应的回调函数
import StateMachine from './libs/state-machine'

let fsm = new StateMachine({
    init: 'pending', // 初始化状态
    transitions: [
        {
            name: 'resolve',
            from: 'pending',
            to: 'fullfilled'
        },
        {
            name: 'reject',
            from: 'pending',
            to: 'rejected'
        },
    ],
    methods: {
        /**
        /* @state 是当前的状态机实例
        /* @data 是执行fsm.resove(xx)传递的参数xx
        */
        onResove(state, data) {
            data.succedList.forEach(fn => fn())
        },
        onReject(state, data) {
            data.failList.forEach(fn => fn())
        }
    }
})

class MyPromise {
    constructor(fn) {
        this.succedList = []
        this.failList = []
        fn(function () {
            fsm.resolve(this)
        }, function () {
            fsm.reject(this)
        })
    }
    then(fullfilledFn, rejectFn) {
        this.succedList.push(fullfilledFn)
        this.failList.push(rejectFn)
    }
}

function loadImg() {
    const promise = new Promise(function (resolve, reject) {
        setTimeout(function () {
            resolve('ok')
        }, 1000)
        // 这里手动开启来测试
        // setTimeout(function () {
        //     reject('fail')
        // }, 1000)

    })
    return promise
}

let result = loadImg()
result.then(function () {
    console.log('fullfilled')
}, function () {
    console.log('reject')
})

 

设计原则验证
  • 将状态对象和主题对象分离,状态的变化逻辑单纯处理
  • 符合开放封闭原则