JavaScript设计模式中的状态模式
Posted 三水草肃
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript设计模式中的状态模式相关的知识,希望对你有一定的参考价值。
状态模式
状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变
状态模式的优缺点
- 优点
- 把状态和行为封装成单独的类,独立而互不影响,也容易新增状态和转换。符合开放封闭原则。
- 避免 Context 增加过多的类,状态切换的逻辑被分布在状态类中。
- 缺点
- 如果会定义许多状态类,逻辑分散,状态逻辑梳理复杂。
状态模式的性能优化点
-
主要是 state 状态对象的创建和销毁
- state 被需要才创建。 如果对象比较庞大,可以使用这个节省内存,避免一些不会用到的对象及时回收。
- state 一开始就创建所有的状态对象,并且始终不销毁。状态改变很频繁的时候使用
-
本例子中(upload2.html)每个 Context 都创建一个 state 对象,实际上 Context 可以共享一个 state 对象,也是享元模式的应用场景之一。
如何做好状态模式
- 状态模式先定义状态,并把所有的状态都封装成单独的对象,统一去维护。健壮性 + 开放封闭
- Light 也被称为上下文 Context,随后在 Light 的构造函数中,我们创建每一种状态类的实例对象,Context 将持有这些状态对象的引用,以便把请求交给状态对象。
/**
* 初始状态模式
* 1. 电灯,电灯开着,按下开关,会切换到关闭状态。电灯关着,按下开关,会切换到开启状态。
* 2. light是从Light类创建出来。
* 3. light对象也要传入状态类的构造函数,以便调用light中的方法
*/
const Light = function ()
this.state = "off"; // 设置灯泡的初始状态
this.button = null; // 电灯开关按钮
;
// 按钮初始化,创建一个真实button节点
Light.prototype.init = function ()
const button = document.createElement("button");
const self = this;
button.innerHTML = "开关";
this.button = document.body.appendChild(button);
console.log(this.button);
this.button.onclick = function ()
self.buttonWasPressed();
;
;
// 开关被按下,程序会调用self.buttonWasPressed方法,开关按下之后的所有行为,都会被封装在这个方法里。
Light.prototype.buttonWasPressed = function ()
if (this.state === "off")
this.state = "on";
console.log("开灯");
else
this.state = "off";
console.log("关灯");
;
const light = new Light();
light.init();
/**
* 以上代码违法开放封闭原则,每次新增状态都需要在buttonWaspressed里进行修改,会改动其余的代码。
* 状态难以察觉,没有一个对象统一维护所有的状态
* 大量使用if else让代码不具备健壮性
*/
/**
* 每次状态改变,状态对象就会给Light传下一次要执行的状态对象。
*/
// off
const OffLight = function (light)
this.light = light;
;
OffLight.prototype.buttonWasPressed = function ()
console.log("弱光");
this.light.setState(this.light.weakLightState); // 切换状态
;
const WeakLight = function (light)
this.light = light;
;
WeakLight.prototype.buttonWasPressed = function ()
console.log("强光");
this.light.setState(this.light.strongLightState); // 切换状态
;
const StrongLight = function (light)
this.light = light;
;
StrongLight.prototype.buttonWasPressed = function ()
console.log("关灯");
this.light.setState(this.light.offLightState); // 切换状态
;
const Light2 = function ()
this.offLightState = new OffLight(this);
this.weakLightState = new WeakLight(this);
this.strongLightState = new StrongLight(this);
this.button = null;
;
// 通过self.currentState.buttonWasPressed()将请求委托给当前持有的状态对象去执行
Light2.prototype.init = function ()
debugger;
const button = document.createElement("button");
const self = this;
this.button = document.body.appendChild(button);
this.button.innerHTML = "开关2";
this.currentState = this.offLightState; // 初始状态
this.button.onclick = function ()
self.currentState.buttonWasPressed();
;
;
Light2.prototype.setState = function (newState)
this.currentState = newState;
;
const light2 = new Light2();
light2.init();
状态模式和策略模式的关系
-
相同点:
- 他们都封装了一系列的算法或者行为,他们的类图看起来一样。
- 都有一个上下文、一些策略或者状态类,上下文把请求委托给这些类来执行。
-
不同点:
- 策略模式的各个策略类是平等又平行的,他们之间没有任何联系,所以客户必须熟知这些策略类的作用,以便客户可以随时主动切换算法;
- 状态模式对应的行为是已经封装好的,状态之间的切换也早被规定好。改变行为是发生在状态模式内部,不需要了解这些细节。这也是状态模式的作用所在。
以上是关于JavaScript设计模式中的状态模式的主要内容,如果未能解决你的问题,请参考以下文章