学习JavaScript设计模式之状态模式

网络营销 2025-04-16 13:29www.168986.cn短视频营销

在JavaScript设计模式的世界里,状态模式是一种非常关键的模式。它主要关注的是事物内部状态的转变,以及这些状态变化如何影响事物的行为。简单来说,就是事物在不同状态下的行为表现不同。

想象一下我们日常生活中的电灯。当电灯处于关闭状态时,按下开关,它会切换到开启状态;再次按下开关,电灯又会关闭。同样的开关,在不同的状态下,表现出的行为是完全不同的。这就是状态模式的核心思想。

一、理解有限状态机

在状态模式中,事物的状态是有限的。在任何时刻,事物都只处于一种状态。当满足一定的条件时,事物会从当前状态转移到另一种状态。

让我们深入一下状态模式的核心思想:将对象的行为与其内部状态紧密关联。当对象的状态改变时,它的行为也会随之改变。在JavaScript中,我们可以通过将不同的状态封装成单独的类,来实现这一模式。这样,当对象的状态改变时,我们可以简单地更换对象当前的状态对象,从而改变对象的行为。

二、电灯程序的示例

假设我们有一个简单的电灯程序,它有三种状态:关灯、弱光和强光。我们可以通过点击按钮来切换电灯的状态。

以下是状态模式的简单实现:

我们为每种状态(关灯、弱光、强光)创建一个类,这些类继承自一个抽象类Light。抽象类Light有一个buttonWasPressed方法,这是一个抽象方法,需要在子类中实现。然后,我们为电灯创建一个实例,并初始化它的状态为关灯状态。在按钮的点击事件中,我们调用当前状态的buttonWasPressed方法。

当我们点击按钮时,当前状态的buttonWasPressed方法会被调用,然后改变电灯的状态。例如,当电灯处于关灯状态时,我们点击按钮,会调用OffLightState的buttonWasPressed方法,这个方法会输出“关灯!”并设置电灯的状态为弱光状态。

通过这种方式,我们可以轻松实现电灯的状态切换,并可以在每种状态下执行不同的操作。这就是状态模式的魅力所在。

一、状态机的构建与运作

设想我们有一个灯光系统,它有三种状态:关灯(OffLightState)、弱光(WeakLightState)和强光(StrongLightState)。我们可以构建一个状态机来管理这些状态及其转换。

我们先定义基础灯光类和三个状态类。

Light 类:

```javascript

function Light() {

this.state = new OffLightState(this); // 初始状态为关灯状态

}

```

OffLightState 类:

当灯光处于关闭状态时,用户按下按钮,将触发 `buttonWasPressed` 方法,切换到下一个状态(这里是弱光状态)。

```javascript

function OffLightState(light) {

this.light = light; // 绑定灯光对象

this.buttonWasPressed = function() {

console.log("关灯");

this.light.setState(new WeakLightState(this.light)); // 切换到弱光状态

};

}

```

类似地,我们可以定义 WeakLightState 和 StrongLightState 类,并实现它们的状态转换逻辑。

二、关于函数声明提升的问题

在 JavaScript 中,函数声明会被提升到普通变量之前。这意味着在代码执行前,函数就已经被加载和准备好了。即使我们先调用 `new A("a");` 和 `new B("b");`,函数 `A` 和 `B` 的声明也会被提前处理。这是一个重要的特性,让我们能够灵活地管理代码的执行顺序。这对于状态机的实现非常重要,因为我们需要确保状态转换的逻辑在正确的上下文中执行。这一点在前面的状态机代码中已经得到了体现。

三、性能优化点

关于状态管理,有两个重要的性能优化点:

(1)如何管理状态对象的创建和销毁?可以考虑仅当状态对象被需要时才创建并随后销毁(对于状态对象比较庞大时),或者一开始就创建好所有的状态对象并始终不销毁(对于状态改变频繁的情况)。这样可以避免不必要的对象创建和销毁开销。

(2)利用享元模式共享一个state对象。这样可以减少内存使用,提高性能。在JavaScript中,我们可以通过对象字面量的方式来实现享元模式的状态共享。

我们来创建一个简单的灯光类,并通过状态机来控制灯光的开关状态。状态机是一种在软件设计中常用的模式,它允许我们的代码在不同的状态之间进行转换,并根据当前状态执行特定的操作。在这个例子中,我们的灯光有两个状态:开和关。

```javascript

// 定义状态机

var FSM = {

off: {

buttonWasPressed: function() {

console.log("关灯");

this.button.textContent = "开启"; // 修改按钮文字为开启

this.currState = this.onState; // 状态切换为开状态

}

},

on: {

buttonWasPressed: function() {

console.log("开灯");

this.button.textContent = "关闭"; // 修改按钮文字为关闭

this.currState = this.offState; // 状态切换为关状态

}

}

};

// 创建Light类并初始化状态机

var Light = function() {

this.currState = FSM.off; // 设置初始状态为关状态

this.button = document.createElement('button'); // 创建按钮元素

thisit(); // 初始化按钮和状态机逻辑

};

Light.prototypeit = function() {

// 设置按钮文字并绑定点击事件到状态机处理函数上

this.button.textContent = '关闭'; // 默认按钮文字为关闭(表示初始状态为关)

document.body.appendChild(this.button); // 将按钮添加到页面中

this.button.addEventListener('click', function() { this.currState.buttonWasPressed(); }); // 添加点击事件监听器,调用当前状态的buttonWasPressed函数处理点击事件

};

```

Copyright © 2016-2025 www.168986.cn 狼蚁网络 版权所有 Power by