前端设计模式 状态模式

状态模式:一个对象有状态变化,每次状态变化都会触发一个逻辑,不能总是用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');
})

 

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

 

posted @ 2019-11-13 07:20  wzndkj  阅读(642)  评论(0编辑  收藏  举报