JavaScript -- 设计模式 行为型设计模式-状态模式

状态模式:当一个对象里面有状态变化,而且当状态发生改变时,会触发一个逻辑(或者行为)。特别当状态比较多时,那么就需要状态模式,不能总是写if else 来控制。

生活中,红绿灯就是一个很好的状态模式的例子。

我们先来看一下简化版状态模式的类图。

我们以红绿灯为例,来写一下代码。

class State {
    constructor(color) {
        this.color = color;
    }
    handle(context) {
        context.setState(this);
    }
}


class Context {
    constructor() {
        this.state = null;
    }
    setState(state) {
        this.state = state;
    }
    getState() {
        return this.state;
    }
}

const context = new Context();

const green = new State("绿灯");
const yellow = new State("黄灯");
const red = new State("红灯");

green.handle(context);
console.log(context.getState().color);
red.handle(context);
console.log(context.getState().color);
yellow.handle(context);
console.log(context.getState().color);

这只是一个简单的例子,演示了如何将状态和操作对象实现分离。

javascript-state-machine  这是一个JS的状态管理库,用法非常简答

我们还是使用红绿灯例子举例

const StateMachine = require("javascript-state-machine");

const fsm = new StateMachine({
    init: "red", //触式默认状态
    transitions: [
        { name: "rTOy", from: "red", to: "yellow" }, //定义变化
        { name: "yTOg", from: "yellow", to: "green" },
        { name: "gTOr", from: "green", to: "red" },
    ],
    methods: { //定义变化 触发的逻辑
        onRTOy: function () {
            console.log("红灯变成黄灯");
        },
        onYTOg: function () {
            console.log("黄灯变成绿灯");
        },
        onGTOr: function () {
            console.log("绿灯变成红灯");
        },
    }
})

const flag = setInterval(()=>{
    if (fsm.is("red")) { //使用is来判断状态
        fsm.rTOy(); //调用定义好的方法
    } else if (fsm.is("yellow")) {
        fsm.yTOg();
    } else {
        fsm.gTOr();
    }  
}, 2000);

 

我们在看一个复杂一点的例子,我们使用上面的那个库,来实现一个非常简单的promise(因为Promise的状态有三个pending fulfilled  rejected)

当状态从pending到fulfilled时,那么就调用resolve  当状态从pending到rejected时 ,那么调用reject

很明显这里面有状态的变化,所以我们使用状态模式写一下。

 

const StateMachine = require("javascript-state-machine");

const fsm = new StateMachine({
    init: "pending",
    transitions: [
        { name: "resolve", from: "pending", to: "fulfilled" },
        { name: "reject", from: "pending", to: "rejected" },
    ],
    methods: {
        onResolve: function (state, resolveFn) { //将成功的所有回调全部调用
            resolveFn.forEach((fn) => fn());
        },
        onReject: function (state, rejectFn) {//将失败的所有回调全部调用
            rejectFn.forEach((fn) => fn());
        }
    }
})

class MyPromise {
    constructor(fn) {
        this.resolveCallBack = [];
        this.rejectCallBack = [];
        fn((target) => {//resolve 函数即把状态把pending转为fulfilled
            fsm.resolve(this.resolveCallBack);
        }, () => {//reject 函数即把状态把pending转为rejected
            fsm.reject(this.rejectCallBack );
        })
    }
    then(resolve = () => {}, reject = () => {}) {
        this.resolveCallBack.push(resolve); //添加成功回调
        this.rejectCallBack.push(reject);
    }
}


function loadImg(src) {
    return new MyPromise((resolve, reject) => {
        const img = document.createElement("img");
        img.onload = function () {
            resolve();
        }
        img.onerror = function () {
            reject();
        }
        img.src = src;
    })
}

const result = loadImg("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3034041308,2252600183&fm=26&gp=0.jpg")

result.then(() => {
    console.log("成功了")
}, () => {
    console.log("失败了")
})

关键的地方 我已经加上了注释,假如你了解promise的工作原理,那么理解起来就不难,不然的话,需要一些时间。

上面代码 演示了如何使用状态模式来实现promise的几种状态管理,当一个对象里面有许多状态而且状态的改变会引发变化,那么你可以试试状态模式。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值