我想学会设计模式之状态模式

156 阅读2分钟

我想学会设计模式之状态模式


这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战


状态模式:对象行为是根据状态改变,而改变的

image-20210814183406660


什么是“状态模式”?

状态模式:对象行为是根据状态改变,而改变的。

正是由于内部状态的变化,导致对外的行为发生了变化。例如:相同的方法在不同时刻被调用,行为可能会有差异。


优缺点

优点:
  • 封装了转化规则,对于大量分支语句,可以考虑使用状态类进一步封装。
  • 每个状态都是确定的,对象行为是可控的
  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
  • 状态模式的实现关键是将事物的状态都封装成单独的类,这个类的各种方法就是“此种状态对应的表现行为”。因此,程序开销会增大。
  • 会增加系统类和对象的个数,且结构与实现都较为复杂。状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式

应用实例

  • 打篮球的时候运动员可以有正常状态、不正常状态和超常状态。
  • 曾侯乙编钟中,'钟是抽象接口','钟A'等是具体状态,'曾侯乙编钟'是具体环境(Context)。

代码实现

ES6 实现

在 JavaScript 中,可以直接用 JSON 对象来代替状态类。

下面代码展示的就是 FSM(有限状态机)里面有 3 种状态:downloadpausedeleted。控制状态转化的代码也在其中。

DownLoad类就是,常说的Context对象,它的行为会随着状态的改变而改变。

const FSM = (() => {
    let currenState = "download";
    return {
        download: {
            click: () => {
                console.log("暂停下载");
                currenState = "pause";
            },
            del: () => {
                console.log("先暂停, 再删除");
            }
        },
        pause: {
            click: () => {
                console.log("继续下载");
                currenState = "download";
            },
            del: () => {
                console.log("删除任务");
                currenState = "deleted";
            }
        },
        deleted: {
            click: () => {
                console.log("任务已删除, 请重新开始");
            },
            del: () => {
                console.log("任务已删除");
            }
        },
        getState: () => currenState
    };
})();
class Download {
    constructor(fsm) {
        this.fsm = fsm;
    }
    handleClick() {
        const { fsm } = this;
        fsm[fsm.getState()].click();
    }
    hanldeDel() {
        const { fsm } = this;
        fsm[fsm.getState()].del();
    }
}
// 开始下载
let download = new Download(FSM);
download.handleClick(); // 暂停下载
download.handleClick(); // 继续下载
download.hanldeDel(); // 下载中,无法执行删除操作
download.handleClick(); // 暂停下载
download.hanldeDel(); // 删除任务