状态模式的关键是区分事物内部的状态,事物内部状态的改变往往会带来事物的行为改变
主要是 state 状态对象的创建和销毁
本例子中(upload2.html)每个 Context 都创建一个 state 对象,实际上 Context 可以共享一个 state 对象,也是享元模式的应用场景之一。
/**
* 初始状态模式
* 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();
相同点:
不同点: