C++实现设计模式---状态模式 (State)

news/2025/1/14 18:05:08/

状态模式 (State)

状态模式 是一种行为型设计模式,它允许对象在运行时根据内部状态的改变来动态改变其行为。通过将状态相关的行为封装到独立的类中,状态模式使得状态的切换更加清晰和灵活。


意图

  • 将对象的行为和状态分离,随着状态的改变动态调整对象的行为。
  • 避免使用大量的 if-elseswitch-case 语句处理状态逻辑。

使用场景

  1. 对象的行为依赖于状态
    • 例如订单的状态(未支付、已支付、已发货)。
  2. 需要动态切换状态
    • 例如游戏角色的动作(站立、行走、奔跑)。
  3. 需要扩展状态逻辑
    • 新增状态时不影响现有逻辑。

参与者角色

  1. 上下文类 (Context)
    • 保存当前状态的引用,提供接口供外部访问,并委托状态对象执行行为。
  2. 状态接口 (State)
    • 定义状态的公共接口。
  3. 具体状态类 (ConcreteState)
    • 实现状态接口并定义该状态下的具体行为。

代码示例

以下代码展示了一个机器人(Robot)的状态模式实现。机器人可以处于“待机状态 (Idle)”、“工作状态 (Working)”和“充电状态 (Charging)”之间切换。

#include <iostream>
#include <memory>
#include <string>// ------------------------------
// 状态接口:定义机器人状态的公共接口
class RobotContext; // 前置声明上下文类class RobotState {
public:virtual ~RobotState() = default; // 虚析构函数,确保多态销毁// 状态行为接口virtual void startWork(RobotContext& context) = 0;     // 开始工作virtual void chargeBattery(RobotContext& context) = 0; // 开始充电virtual std::string getStateName() const = 0;          // 获取状态名称
};// ------------------------------
// 上下文类:机器人
class RobotContext {
private:std::unique_ptr<RobotState> state; // 当前机器人状态,使用 unique_ptr 管理状态对象public:explicit RobotContext(std::unique_ptr<RobotState> initialState) : state(std::move(initialState)) {}// 设置新的状态void setState(std::unique_ptr<RobotState> newState) {state = std::move(newState);}// 委托开始工作行为给当前状态void startWork() {state->startWork(*this);}// 委托充电行为给当前状态void chargeBattery() {state->chargeBattery(*this);}// 获取当前状态名称std::string getStateName() const {return state->getStateName();}
};// ------------------------------
// 具体状态类:工作状态
class WorkingState : public RobotState {
public:void startWork(RobotContext& context) override {std::cout << "机器人已经在工作中,无法重复开始工作。
";}void chargeBattery(RobotContext& context) override {std::cout << "机器人停止工作,切换到充电状态。
";context.setState(std::make_unique<class ChargingState>()); // 切换到“充电状态”}std::string getStateName() const override {return "工作状态";}
};// ------------------------------
// 具体状态类:充电状态
class ChargingState : public RobotState {
public:void startWork(RobotContext& context) override {std::cout << "机器人充电完成,切换到工作状态。
";context.setState(std::make_unique<class WorkingState>()); // 切换到“工作状态”}void chargeBattery(RobotContext& context) override {std::cout << "机器人已经在充电中,无法重复充电。
";}std::string getStateName() const override {return "充电状态";}
};// ------------------------------
// 具体状态类:待机状态
class IdleState : public RobotState {
public:void startWork(RobotContext& context) override {std::cout << "机器人开始工作,切换到工作状态。
";context.setState(std::make_unique<class WorkingState>()); // 切换到“工作状态”}void chargeBattery(RobotContext& context) override {std::cout << "机器人开始充电,切换到充电状态。
";context.setState(std::make_unique<class ChargingState>()); // 切换到“充电状态”}std::string getStateName() const override {return "待机状态";}
};// ------------------------------
// 客户端代码
int main() {// 初始化机器人为“待机状态”RobotContext robot(std::make_unique<IdleState>());// 获取当前状态并输出std::cout << "当前机器人状态: " << robot.getStateName() << "
";// 机器人开始工作robot.startWork();std::cout << "当前机器人状态: " << robot.getStateName() << "
";// 机器人充电robot.chargeBattery();std::cout << "当前机器人状态: " << robot.getStateName() << "
";// 再次开始工作robot.startWork();std::cout << "当前机器人状态: " << robot.getStateName() << "
";return 0;
}

代码解析

1. 状态接口 (RobotState)
  • 定义公共接口
    • 包括 startWorkchargeBatterygetStateName 三个接口。
    • 每个具体状态类都必须实现这些接口,定义具体的行为。
2. 上下文类 (RobotContext)
  • 负责管理当前状态
    • RobotContext 保存当前状态的智能指针(std::unique_ptr),并负责管理状态对象的生命周期。
  • 行为委托
    • 调用 startWorkchargeBattery 时,行为委托给当前状态对象。
  • 状态切换
    • 通过 setState 方法切换状态,使用 std::make_unique 创建新的状态对象。
3. 具体状态类
  • IdleState (待机状态)
    • 允许切换到“工作状态”或“充电状态”。
  • WorkingState (工作状态)
    • 如果重复调用 startWork,提示“已在工作中”。
    • 支持切换到“充电状态”。
  • ChargingState (充电状态)
    • 如果重复调用 chargeBattery,提示“已在充电中”。
    • 支持切换到“工作状态”。
4. 状态切换逻辑
  • 每个状态类都可以通过 context.setState(std::make_unique<NewState>()); 切换到其他状态。
  • 切换状态时使用 std::unique_ptr 管理状态对象,确保内存安全。

运行结果

运行程序后,输出如下:

当前机器人状态: 待机状态
机器人开始工作,切换到工作状态。
当前机器人状态: 工作状态
机器人停止工作,切换到充电状态。
当前机器人状态: 充电状态
机器人充电完成,切换到工作状态。
当前机器人状态: 工作状态

优缺点

优点
  1. 封装状态逻辑
    • 每个状态的行为封装在独立的类中,方便维护和扩展。
  2. 动态切换状态
    • 通过 setState 动态切换状态,逻辑清晰。
  3. 消除条件语句
    • 使用多态机制避免了大量的 if-elseswitch-case 语句。
缺点
  1. 类数量增加
    • 每种状态都需要单独定义一个类,可能导致类数量较多。
  2. 上下文和状态耦合
    • 状态类依赖上下文类的操作。

适用场景

  1. 对象的行为依赖于状态
    • 如订单状态、文件操作等。
  2. 需要动态切换状态
    • 系统需要根据当前状态动态改变行为。

总结

状态模式通过将状态的行为封装到独立的类中,实现了对象的动态行为调整,是有限状态机的优雅实现方式。它特别适用于需要频繁切换状态且每种状态具有独立逻辑的场景。


http://www.ppmy.cn/news/1563090.html

相关文章

Windows安装Ubuntu子系统图形化工具

Windows如何使用WSL方式安装Ubuntu&#xff0c;可以参考&#xff1a;https://blog.csdn.net/xiangzhihong8/article/details/145044370。接下来&#xff0c;我们说一下如何安装Ubuntu的图形化系统。 为了测试&#xff0c;这里介绍两种常见的图形化工具。第一种为VcXsrv Gnome…

34_Lua概述与环境安装指南

从这个模块开始带领带领大家来学习Lua相关的知识。有小伙伴可能会问了问什么要学习Lua?因为在后续的模块中我们需要写Redis脚本、Web开发中编写Nginx脚本等,这些都需要通过Lua语言来实现,因此对Lua的语法我们需要简单了解和掌握必要的知识。 1 Lua概述 1.1 Lua介绍 Lua诞…

TensorFlow Quantum快速编程(基本篇)

一、TensorFlow Quantum 概述 1.1 简介 TensorFlow Quantum(TFQ)是由 Google 开发的一款具有开创性意义的开源库,它宛如一座桥梁,巧妙地将量子计算与 TensorFlow 强大的机器学习功能紧密融合。在当今科技飞速发展的时代,传统机器学习虽已取得诸多瞩目成就,然而面对日益…

C#/.NET/.NET Core技术前沿周刊 | 第 20 期(2025年1.1-1.5)

前言 C#/.NET/.NET Core技术前沿周刊&#xff0c;你的每周技术指南针&#xff01;记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用、最有价值的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿&#xff0c;助力技术成长与视野拓宽。 欢迎投稿、推荐…

Android 自定义混淆字典

添加下面的代码&#xff0c;用新的混淆字典&#xff0c;随机大小写字母组合 package com.jiuhong.mbtirgtest.util;import java.io.FileWriter; import java.io.IOException; import java.util.HashSet; import java.util.Random; import java.util.Set;public class Obfuscat…

相机小孔成像模型与透视变换

0 背景 本文用于记录小孔相机成像的数学模型推导&#xff0c;并讨论特定条件下两个相机之间看到图像的变换关系。 1 小孔成像模型 小孔成像模型如上图所示。物理世界发光点P&#xff0c;经过小孔O投影到物理成像平面&#xff0c;形成像点I’。 简易起见&#xff0c;构造虚拟成…

全栈面试(一)Basic/微服务

文章目录 项目地址一、Basic InterviewQuestions1. tell me about yourself?2. tell me about a time when you had to solve a complex code problem?3. tell me a situation that you persuade someone at work?4. tell me a about a confict with a teammate and how you…

回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测

回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测 目录 回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测。 程序设计 完整代码&#xff1a;回…