设计模式之状态模式

2019-06-14  本文已影响0人  回调的幸福时光

一、基础介绍

状态模式:允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

状态模式 UML 类图

二、例子讲解

以 promise 为例,我们知道 promise 是对异步操作的封装,内部有 3 种状态,每种状态对应不同的行为。

以下的代码采用状态模式实现了简单版的 promise 。
注意 then 方法并未提供完整功能,没有继续返回 promise ,所以无法链式调用。

思考步骤:

//  有限状态机(Finite State Machine)
const FSM = {
  pending: {
    name: 'pending',
    done() {
      this.state = FSM.pending;
      console.log('pending 中...');
    }
  },
  resolved: {
    name: 'resolved',
    done() {
      if (this.state.name !== 'pending') return;
      this.state = FSM.resolved;
      console.log('状态更改为 resolved');
      // 调用 onResolve
      this.onResolve();
    }
  },
  rejected: {
    name: 'rejected',
    done() {
      if (this.state.name !== 'pending') return;
      this.state = FSM.rejected;
      console.log('状态更改为 rejected');
      // 调用 onReject
      this.onReject();
    }
  }
}

class myPromise {
  constructor(executor) {
    // 初始化状态为 pendding
    this.state = FSM.pending;
    FSM.pending.done.call(this);
    
    // 异步操作回调函数初始化
    this.onResolve = Function.prototype;
    this.onReject= Function.prototype;
    
    // 执行 executor
    executor(() => {
      FSM.resolved.done.call(this);
    },() => {
      FSM.rejected.done.call(this);
    })
  }

  then(onResolve, onReject) {
    // 校验 onResolve
    if (onResolve  && typeof onResolve !== 'function') {
      throw new Error("出错啦~");
    }
    
    // 校验 onReject 
    if (onReject && typeof onReject !== 'function') {
      throw new Error("出错啦~");
    }

    this.onResolve = typeof onResolve === 'function' ? onResolve : () => {};
    this.onReject = typeof onReject=== 'function' ? onReject : () => { throw new Error("出错啦~");};
  }
}

测试代码:

 // 测试代码
function ajax(type=true) {
  const promise = new myPromise((resolve, reject) => {
    setTimeout(() => {
      if (type) {
        resolve();
      } else {
        reject();
      }
    }, 1000);
  });
  return promise;
}
const response_1 = ajax();
response_1.then(()=>{
    console.log('response_1 请求成功后的处理');
},()=>{
    console.log('response_1 请求失败后的处理');
});

const response_2 = ajax(false);
response_2.then(()=>{
    console.log('response_2 请求成功后的处理');
},()=>{
    console.log('response_2 请求失败后的处理');
});
测试代码运行结果

状态变更不可逆的处理

 if (this.state.name !== 'pending') return;
状态变更是不可逆的

github 上的 JavaScript 有限状态机库

链接:jakesgordon/javascript-state-machine

三、应用场景

红绿灯、灯的开关、文件上传、游戏中任务的动作状态等。

四、优缺点

优点:

缺点:

五、状态模式中的性能优化

  1. state 对象的创建和销毁
  1. 利用享元模式,可以使个 Context 对象共享 state 对象。

六、策略模式和状态模式的关系

相同点:

不同点:

推荐阅读 设计模式之禅:策略模式VS状态模式

参考

《JavaScript 设计模式与开发实践》曾探
《JavaScript 设计模式》张容铭
Javascript设计模式系统讲解与应用

上一篇 下一篇

猜你喜欢

热点阅读