前端设计模式 状态模式
状态模式:一个对象有状态变化,每次状态变化都会触发一个逻辑,不能总是用if...else来控制
比如红绿灯
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; } // 获取状态 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())
场景1:有限状态机
有限的状态、以及在这些状态之间的变化。如交通信号灯
使用开源lib: javascript-state-machine
https://github.com/jakesgordon/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();
场景2:写一个简单的Promise
Promis是个有限状态机,三种状态,pending fullfilled rejected。
状态变化可以由 pending -> fullfilled 或者 pending -> rejected
不能逆向变化
import StateMachine from 'javascript-state-machine'; // 状态机模型 var fsm = new StateMachine({ init: 'pending', // 初始化状态 transitions:[{ name: 'resolve', from: 'pending', to: 'fullfilled' }, { name: 'reject', from: 'pending', to: 'rejected' }], method: { // 成功 onResolve: function(state, data) { // 参数:state - 当前状态实例; data - fsm.resove(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 = []; // promise传入的是一个函数,两个参数,一个resolve,一个reject fn(() => { // resove 函数 fsm.resolve(this); // 触发状态机模型方法,传递当前这个promise对象 }, () => { // reject 函数 fsm.reject(this); }) } // promise实现一个.then的方法 then(successFn, failFn) { this.successList.push(successFn); this.failList.push(failFn); } } // 测试 function loadImg(src){ const promise = new MyPromise((resolve, reject)=>{ let img = document.createElement('img'); img.onload = function() { resolve(img); } img.onerror = function(err) { reject(err) } img.src = src }) return promise; } let src = 'https://www.baidu.com/img/bd_logo1.png' let result = loadImg(src); result.then(res => { console.log('ok1'); }, err => { console.log('fail1'); })
设计原则验证
将状态对象和主体对象分离,状态的变化逻辑单独处理
符合开放封闭原则