0

0

如何在C++中实现状态机_状态模式应用实例

尼克

尼克

发布时间:2025-06-23 19:31:01

|

426人浏览过

|

来源于php中文网

原创

状态模式是一种通过封装状态行为来实现状态切换的面向对象设计方式。1. 它将每个状态定义为独立类,使状态变化驱动行为改变,从而提升代码可维护性与扩展性;2. 通过上下文对象(如door)持有当前状态并委托请求,避免了冗长条件判断;3. 状态转换在具体状态类中处理,新增状态无需修改已有逻辑;4. 相比策略模式,其侧重内部状态而非外部算法选择;5. 在游戏开发中广泛用于角色状态管理;6. 多线程环境下需结合互斥锁确保状态切换安全。

如何在C++中实现状态机_状态模式应用实例

状态机,简单来说,就是在不同条件下切换自身状态的机制。在C++里,实现状态机的方法有很多,可以用switch-case,也可以用函数指针,但更优雅、更面向对象的方式,通常会选择状态模式。状态模式允许对象在内部状态改变时改变它的行为,看起来好像修改了它的类。

如何在C++中实现状态机_状态模式应用实例

解决方案

如何在C++中实现状态机_状态模式应用实例

状态模式的核心在于将状态封装成独立的类,然后让上下文对象持有当前状态的引用。当上下文对象需要根据状态执行不同的行为时,它会将请求委托给当前状态对象。这样,我们就可以在不修改上下文对象代码的情况下,通过增加新的状态类来扩展状态机的行为。

立即学习C++免费学习笔记(深入)”;

如何在C++中实现状态机_状态模式应用实例

一个简单的例子:假设我们有一个门,它可以处于打开、关闭、锁定三种状态。

  1. 定义状态接口:
class DoorState {
public:
    virtual void open(class Door* door) {}
    virtual void close(class Door* door) {}
    virtual void lock(class Door* door) {}
    virtual void unlock(class Door* door) {}
    virtual ~DoorState() {} // 确保基类有虚析构函数
};
  1. 实现具体状态类:
#include 

// Forward declaration of Door class

class DoorState {
public:
    virtual void open(class Door* door);
    virtual void close(class Door* door);
    virtual void lock(class Door* door);
    virtual void unlock(class Door* door);
    virtual ~DoorState() {} // Ensure base class has virtual destructor
};


class OpenState : public DoorState {
public:
    void close(Door* door) override;
    void lock(Door* door) override;
};

class ClosedState : public DoorState {
public:
    void open(Door* door) override;
    void lock(Door* door) override;
};

class LockedState : public DoorState {
public:
    void unlock(Door* door) override;
};


class Door {
public:
    DoorState* state;

    Door(DoorState* initialState) : state(initialState) {}

    void setState(DoorState* newState) {
        delete state; // Important: Prevent memory leaks
        state = newState;
    }

    void open() {
        state->open(this);
    }

    void close() {
        state->close(this);
    }

    void lock() {
        state->lock(this);
    }

    void unlock() {
        state->unlock(this);
    }

    ~Door() {
        delete state; // Clean up the state object
    }
};

void OpenState::close(Door* door) {
    std::cout << "Closing the door.\n";
    door->setState(new ClosedState());
}

void OpenState::lock(Door* door) {
    std::cout << "Cannot lock an open door.\n";
}

void ClosedState::open(Door* door) {
    std::cout << "Opening the door.\n";
    door->setState(new OpenState());
}

void ClosedState::lock(Door* door) {
    std::cout << "Locking the door.\n";
    door->setState(new LockedState());
}

void LockedState::unlock(Door* door) {
    std::cout << "Unlocking the door.\n";
    door->setState(new ClosedState());
}


int main() {
    Door* door = new Door(new ClosedState()); // Start with the door closed

    door->open();
    door->close();
    door->lock();
    door->unlock();
    //door->unlock(); // Example of unlocking when already unlocked - no transition

    delete door; // Clean up the Door object
    return 0;
}
  1. 上下文对象(Door):

Door类持有当前状态的指针,并提供open()、close()、lock()、unlock()方法,这些方法会将请求委托给当前状态对象。

状态模式的优点在于,它使得状态的切换和行为的改变更加清晰和可维护。每种状态都封装在自己的类中,易于理解和修改。而且,增加新的状态也很容易,只需要创建新的状态类即可,不需要修改现有的代码。

状态模式的缺点是,如果状态很多,类的数量也会很多,可能会增加代码的复杂性。另外,状态之间的转换可能会比较复杂,需要仔细设计。

状态模式与策略模式的区别

红墨
红墨

一站式小红书图文生成器

下载

状态模式和策略模式都是处理对象行为变化的模式,但它们的应用场景有所不同。状态模式主要关注对象内部状态的变化,以及状态变化引起的行为改变。而策略模式则关注算法的选择,允许客户端在运行时选择不同的算法。

简单来说,状态模式是对象自身状态驱动行为的改变,策略模式是客户端选择不同的算法来完成任务。

状态模式在游戏开发中的应用?

在游戏开发中,状态模式应用广泛。例如,一个角色可以有多种状态,如Idle、Walking、Running、Jumping、Attacking等。每种状态对应不同的行为。使用状态模式可以清晰地管理角色的状态和行为,使得代码更加模块化和易于维护。

比如,角色在Attacking状态下,不能执行Jumping操作,或者Running状态下,可以切换到Attacking状态。这些状态之间的转换和行为的改变,都可以通过状态模式来实现。

状态模式的线程安全性问题?

如果多个线程同时访问和修改状态机的状态,可能会出现线程安全问题。为了保证线程安全,可以使用互斥锁(Mutex)或其他同步机制来保护状态的访问和修改。

例如,可以在Door类的setState()方法中使用互斥锁来防止多个线程同时修改状态:

#include 

class Door {
public:
    DoorState* state;
    std::mutex mtx; // 添加互斥锁

    Door(DoorState* initialState) : state(initialState) {}

    void setState(DoorState* newState) {
        std::lock_guard lock(mtx); // 加锁
        delete state;
        state = newState;
    }

    // ... 其他方法 ...
};

这样,在修改状态之前,会先获取互斥锁,防止其他线程同时修改状态,从而保证线程安全。当然,在状态类的各个方法中,如果涉及到共享数据的访问和修改,也需要使用互斥锁或其他同步机制来保护。

相关专题

更多
switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

518

2023.09.21

Java switch的用法
Java switch的用法

Java中的switch语句用于根据不同的条件执行不同的代码块。想了解更多switch的相关内容,可以阅读本专题下面的文章。

404

2024.03.13

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

54

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

46

2025.11.27

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

989

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

50

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2025.12.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

471

2023.08.10

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.7万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号