打印

C语言的设计模式---状态机模式

[复制链接]
148|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keer_zu|  楼主 | 2025-5-30 16:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

在C语言中实现状态机模式(State Pattern)可以通过函数指针+状态结构体模拟面向对象的多态行为。以下是一个完整的示例,以电灯开关(On/Off)为例:

#include <stdio.h>

// 状态接口(模拟抽象类)
typedef struct State State;
struct State {
    void (*handle)(void *context); // 处理函数指针
};

// 上下文(持有当前状态)
typedef struct {
    State *current_state;
} Context;

// 具体状态:开
void on_state_handle(void *context);
State OnState = { .handle = on_state_handle };

// 具体状态:关
void off_state_handle(void *context);
State OffState = { .handle = off_state_handle };

//--- 状态行为实现 ---
void on_state_handle(void *context) {
    Context *ctx = (Context *)context;
    printf("灯已开,执行关闭操作\n");
    ctx->current_state = &OffState; // 切换到关状态
}

void off_state_handle(void *context) {
    Context *ctx = (Context *)context;
    printf("灯已关,执行开启操作\n");
    ctx->current_state = &OnState; // 切换到开状态
}

//--- 上下文操作 ---
void init_context(Context *ctx) {
    ctx->current_state = &OffState; // 初始状态为关
}

void request(Context *ctx) {
    ctx->current_state->handle(ctx); // 委托给当前状态处理
}

//--- 测试代码 ---
int main() {
    Context ctx;
    init_context(&ctx);

    // 模拟用户操作
    for (int i = 0; i < 4; i++) {
        request(&ctx); // 每次请求触发状态转换
    }

    return 0;
}

输出结果:

灯已关,执行开启操作
灯已开,执行关闭操作
灯已关,执行开启操作
灯已开,执行关闭操作

关键设计解析:

  1. 状态接口(State)
    • 使用函数指针 handle模拟虚函数
    • 所有具体状态必须实现该函数
  2. 具体状态(OnState/OffState)
    • 全局单例状态对象(避免重复创建)
    • handle()中实现状态转移逻辑
  3. 上下文(Context)
    • 持有 current_state指针指向当前状态
    • request()方法委托给状态对象处理
  4. 状态转移
    • 在状态处理函数中直接修改 context->current_state
    • 符合开闭原则:新增状态无需修改上下文

扩展新状态步骤(以添加闪烁状态为例):

// 1. 定义新状态
void blinking_state_handle(void *context);
State BlinkingState = { .handle = blinking_state_handle };

// 2. 实现行为逻辑
void blinking_state_handle(void *context) {
    Context *ctx = (Context *)context;
    printf("闪烁中,切换到关闭状态\n");
    ctx->current_state = &OffState;
}

// 3. 在现有状态中添加转移(如在OnState中)
void on_state_handle(void *context) {
    /* ... */
    if(需要闪烁) ctx->current_state = &BlinkingState;
}

优势:

  1. 解耦状态逻辑:每个状态独立封装行为
  2. 消除条件分支:避免复杂的switch-case语句
  3. 可扩展性:符合开放封闭原则
  4. 状态转移显式化:转移逻辑在状态内部明确声明

经典应用场景:TCP连接状态、工控系统流程、游戏AI行为、协议解析器等需要清晰状态转换逻辑的系统。

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1446

主题

12782

帖子

53

粉丝