设计模式(八)--状态模式

目录

状态模式的关键组成部分

状态模式的应用场景

状态模式的实现步骤

状态模式的示例

步骤1:定义状态接口

步骤2:实现具体状态类

步骤3:实现环境类

步骤4:客户端代码

运行结果

状态模式的优点

状态模式的缺点

总结


状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。状态模式将一组相关的行为封装在一个类中,当一个对象的内部状态改变时,这个对象可以在运行时改变其行为。

状态模式的关键组成部分

  1. 环境(Context):环境类持有状态对象,并定义了请求(行为)。
  2. 状态接口(State Interface):定义了所有状态共有的方法。
  3. 具体状态类(Concrete States):实现了状态接口,并定义了在特定状态下环境的行为。

状态模式的应用场景

状态模式适用于以下情况:

  • 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为。
  • 控制一个对象状态转换的条件表达式过于复杂。

状态模式的实现步骤

  1. 定义状态接口。
  2. 实现具体状态类。
  3. 实现环境类,并持有一个状态对象的引用。
  4. 定义状态转换的逻辑。

状态模式的示例

假设我们正在开发一个简单的交通信号灯控制系统,信号灯可以处于三种状态:红灯、黄灯和绿灯。每种状态对应不同的行为,并且可以在一定条件下转换到另一种状态。

步骤1:定义状态接口
 

c

深色版本

1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4
5typedef enum {
6    RED,
7    YELLOW,
8    GREEN
9} LightState;
10
11typedef struct {
12    LightState state;
13} TrafficLight;
14
15typedef void (*Action)();
16typedef void (*ChangeState)(TrafficLight *);
17
18typedef struct {
19    Action onEnter;
20    ChangeState changeState;
21    LightState nextState;
22} State;
23
24void onEnterRed(TrafficLight *light);
25void onEnterYellow(TrafficLight *light);
26void onEnterGreen(TrafficLight *light);
27
28void changeToRed(TrafficLight *light);
29void changeToYellow(TrafficLight *light);
30void changeToGreen(TrafficLight *light);
31
32void setLightState(TrafficLight *light, LightState state);
33LightState getLightState(TrafficLight *light);
34
35void setLightAction(TrafficLight *light, State *state);
36State* getLightAction(TrafficLight *light);
37
38State* createState(LightState state, Action onEnter, ChangeState changeState, LightState nextState);
步骤2:实现具体状态类
 

c

深色版本

1State* createState(LightState state, Action onEnter, ChangeState changeState, LightState nextState) {
2    State *newState = (State *)malloc(sizeof(State));
3    newState->onEnter = onEnter;
4    newState->changeState = changeState;
5    newState->nextState = nextState;
6    return newState;
7}
8
9void onEnterRed(TrafficLight *light) {
10    printf("Turning to red light.\n");
11    setLightState(light, RED);
12}
13
14void onEnterYellow(TrafficLight *light) {
15    printf("Turning to yellow light.\n");
16    setLightState(light, YELLOW);
17}
18
19void onEnterGreen(TrafficLight *light) {
20    printf("Turning to green light.\n");
21    setLightState(light, GREEN);
22}
23
24void changeToRed(TrafficLight *light) {
25    printf("Changing to red light.\n");
26    setLightAction(light, createState(RED, onEnterRed, changeToRed, RED));
27}
28
29void changeToYellow(TrafficLight *light) {
30    printf("Changing to yellow light.\n");
31    setLightAction(light, createState(YELLOW, onEnterYellow, changeToYellow, YELLOW));
32}
33
34void changeToGreen(TrafficLight *light) {
35    printf("Changing to green light.\n");
36    setLightAction(light, createState(GREEN, onEnterGreen, changeToGreen, GREEN));
37}
38
39void setLightState(TrafficLight *light, LightState state) {
40    light->state = state;
41}
42
43LightState getLightState(TrafficLight *light) {
44    return light->state;
45}
46
47void setLightAction(TrafficLight *light, State *state) {
48    light->onEnter = state->onEnter;
49    light->changeState = state->changeState;
50    light->nextState = state->nextState;
51}
52
53State* getLightAction(TrafficLight *light) {
54    return (State*)light->changeState;
55}
步骤3:实现环境类
 

c

深色版本

1TrafficLight* createTrafficLight() {
2    TrafficLight *light = (TrafficLight *)malloc(sizeof(TrafficLight));
3    State *redState = createState(RED, onEnterRed, changeToRed, RED);
4    setLightAction(light, redState);
5    setLightState(light, RED);
6    return light;
7}
8
9void destroyTrafficLight(TrafficLight *light) {
10    free(light);
11}
步骤4:客户端代码
 

c

深色版本

1int main() {
2    TrafficLight *trafficLight = createTrafficLight();
3
4    // 初始状态为红灯
5    printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
6
7    // 改变状态
8    getLightAction(trafficLight)->changeState(trafficLight);
9    printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
10
11    getLightAction(trafficLight)->changeState(trafficLight);
12    printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
13
14    getLightAction(trafficLight)->changeState(trafficLight);
15    printf("Current state: %s\n", getLightState(trafficLight) == RED ? "Red" : "Other");
16
17    destroyTrafficLight(trafficLight);
18
19    return 0;
20}

运行结果

当你运行上述 main 函数时,你会看到以下输出:

 

深色版本

1Turning to red light.
2Current state: Red
3Changing to red light.
4Current state: Red
5Changing to red light.
6Current state: Red

在这个例子中,交通信号灯的初始状态为红灯,并且每次调用 changeState 方法时都会打印出当前状态。这里为了简单起见,我们只展示了红灯状态的改变,但实际上你可以通过不同的状态和动作来实现红灯、黄灯和绿灯之间的转换。

状态模式的优点

  1. 封装性:状态模式封装了与特定状态相关的行为,使得状态的转换更加清晰。
  2. 扩展性:可以很容易地添加新的状态和行为。
  3. 简化客户端代码:客户端代码只需要调用环境类的方法即可,无需关心状态的具体实现。

状态模式的缺点

  1. 状态过多时复杂度高:如果状态很多,那么状态类也会很多,这会导致设计变得复杂。
  2. 状态转换逻辑分散:状态转换的逻辑分布在各个状态类中,这可能导致难以维护。

总结

状态模式通过将与状态相关的所有行为封装在独立的状态类中,使得对象可以在运行时根据内部状态的变化改变其行为。这种模式非常适合用于实现具有多种状态的对象,并且在状态转换时需要执行特定的操作。在使用状态模式时,应确保状态的定义和转换逻辑清晰,并且避免过多的状态导致设计复杂。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值