状态模式(State Pattern)

状态模式(State Pattern)

如果任务的执行过程是有多个不同状态的(比如初始化、运行中、完成等),你可以使用状态模式。每个状态可以有不同的行为,使得任务的状态管理更加清晰和可维护。

示例:
cpp 复制代码
class TaskState {
public:
    virtual void handle() = 0;  // 处理状态
};

class InitializedState : public TaskState {
public:
    void handle() override {
        // 初始化状态下的处理
    }
};

class RunningState : public TaskState {
public:
    void handle() override {
        // 运行状态下的处理
    }
};

class Task {
private:
    TaskState *state;

public:
    void setState(TaskState *state) {
        this->state = state;
    }

    void run() {
        state->handle();
    }
};

状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,从而让对象看起来像是改变了其类。这种模式非常适合处理对象在不同状态下具有不同行为的场景。

状态模式的核心概念

  1. Context(上下文):

    • 包含一个对状态对象的引用,通过这个引用调用状态对象的方法。
    • 客户端通过上下文对象与状态对象交互。
  2. State(状态接口):

    • 定义了一个接口,用于封装与状态相关的操作。
    • 所有具体状态类都实现这个接口。
  3. ConcreteState(具体状态类):

    • 实现了状态接口,具体定义了对象在某个状态下的行为。
    • 可以访问上下文对象,以便在需要时改变上下文的状态。

示例代码解析

以下是一个完整的状态模式示例,包括上下文类、状态接口和具体状态类。

1. 状态接口(State)
cpp 复制代码
class TaskState {
public:
    virtual ~TaskState() {}
    virtual void handle(Task* task) = 0;  // 处理状态
};
2. 具体状态类(ConcreteState)
cpp 复制代码
class InitializedState : public TaskState {
public:
    void handle(Task* task) override {
        std::cout << "Task is in Initialized State" << std::endl;
        // 初始化状态下的处理逻辑
        // 可以在这里改变任务的状态
        task->setState(new RunningState());
    }
};

class RunningState : public TaskState {
public:
    void handle(Task* task) override {
        std::cout << "Task is in Running State" << std::endl;
        // 运行状态下的处理逻辑
        // 可以在这里改变任务的状态
        task->setState(new CompletedState());
    }
};

class CompletedState : public TaskState {
public:
    void handle(Task* task) override {
        std::cout << "Task is in Completed State" << std::endl;
        // 完成状态下的处理逻辑
        // 任务完成,不再改变状态
    }
};
3. 上下文类(Context)
cpp 复制代码
class Task {
private:
    TaskState* state;

public:
    Task() : state(nullptr) {}

    void setState(TaskState* newState) {
        if (state) {
            delete state;  // 释放旧状态
        }
        state = newState;
    }

    void run() {
        if (state) {
            state->handle(this);  // 调用当前状态的处理方法
        }
    }

    ~Task() {
        if (state) {
            delete state;  // 释放状态对象
        }
    }
};

使用示例

以下是如何使用状态模式来管理任务状态的示例:

cpp 复制代码
#include <iostream>

int main() {
    // 创建任务对象
    Task task;

    // 设置初始状态为初始化状态
    task.setState(new InitializedState());

    // 运行任务
    task.run();  // 输出: Task is in Initialized State
    task.run();  // 输出: Task is in Running State
    task.run();  // 输出: Task is in Completed State

    return 0;
}

输出

复制代码
Task is in Initialized State
Task is in Running State
Task is in Completed State

状态模式的用途

  1. 清晰的状态管理:

    • 状态模式将每个状态的行为封装在独立的类中,使得状态管理更加清晰和可维护。
    • 每个状态类只关注自己的行为,符合单一职责原则。
  2. 动态状态切换:

    • 对象可以在运行时动态切换状态,而不需要在上下文类中编写大量的条件语句。
    • 状态的切换逻辑由状态类本身管理,减少了上下文类的复杂性。
  3. 扩展性:

    • 添加新的状态时,只需添加一个新的状态类,而不需要修改现有的上下文类或状态类。
    • 符合开闭原则(对扩展开放,对修改封闭)。

与状态观测器的关系

状态模式和状态观测器(Observer Pattern)是两种不同的设计模式,但它们可以结合使用:

  • 状态模式:

    • 主要用于管理对象的内部状态和行为。
    • 通过状态类的切换来改变对象的行为。
  • 状态观测器(Observer Pattern):

    • 主要用于实现对象之间的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都会得到通知并自动更新。
    • 适用于多对多的依赖关系,例如事件驱动系统。

结合使用示例

假设你需要在任务状态改变时通知其他对象,可以结合状态模式和状态观测器模式:

  1. 定义 Observer 接口:

    cpp 复制代码
    class Observer {
    public:
        virtual void update(const std::string& message) = 0;
    };
  2. 定义 Subject 类:

    cpp 复制代码
    class Subject {
    private:
        std::vector<Observer*> observers;
    public:
        void attach(Observer* observer) {
            observers.push_back(observer);
        }
    
        void notify(const std::string& message) {
            for (Observer* observer : observers) {
                observer->update(message);
            }
        }
    };
  3. 让 Task 类继承 Subject:

    cpp 复制代码
    class Task : public Subject {
    private:
        TaskState* state;
    
    public:
        Task() : state(nullptr) {}
    
        void setState(TaskState* newState) {
            if (state) {
                delete state;
            }
            state = newState;
            notify("Task state changed");  // 通知观察者
        }
    
        void run() {
            if (state) {
                state->handle(this);
            }
        }
    
        ~Task() {
            if (state) {
                delete state;
            }
        }
    };
  4. 定义具体的 Observer:

    cpp 复制代码
    class TaskLogger : public Observer {
    public:
        void update(const std::string& message) override {
            std::cout << "Log: " << message << std::endl;
        }
    };
  5. 使用示例:

    cpp 复制代码
    int main() {
        Task task;
        task.attach(new TaskLogger());
    
        task.setState(new InitializedState());
        task.run();
        task.run();
        task.run();
    
        return 0;
    }

输出

复制代码
Log: Task state changed
Task is in Initialized State
Log: Task state changed
Task is in Running State
Log: Task state changed
Task is in Completed State

总结

  • 状态模式:用于管理对象的内部状态和行为,通过状态类的切换来改变对象的行为。
  • 状态观测器模式:用于实现对象之间的依赖关系,当一个对象的状态改变时,通知所有依赖于它的对象。
  • 结合使用:可以通过状态模式管理状态,同时使用状态观测器模式通知其他对象状态的变化。

希望这些解释和示例能帮助你更好地理解状态模式及其用途。

相关推荐
大江东去浪淘尽千古风流人物4 天前
【HexVIO】DSP卸载双目惯性VIO:Hexagon向量化前端与单帧融合调度深度解析
前端·状态模式·slam·dsp·vio·hexagon·移动端加速
吃一碗粉只付一碗钱5 天前
12-给SPA友好的401和403响应
c#·状态模式
sunlifenger5 天前
嵌入式部署,解锁张家港智慧灯杆的“极简组网”密码
科技·状态模式
上火的金鱼妹6 天前
关于多进程sse连接通知的实战
javascript·状态模式·sse
阿俊-全栈开发6 天前
LikeShop 小程序商城首页可配置弹窗的设计与实现(Java + uni-app)
小程序·状态模式·likeshop·likeshop开源商城
lingyubb7 天前
配音工具怎么选?从 TTS 合成链路看 6 个可量化参数
状态模式
平头哥技术团队8 天前
从预订问到退房:一间山野民宿的数字人「旅程地图」——Theme07_Homestay.vue 端到端拆解
状态模式·数字人
未来之窗软件服务9 天前
web网络请求竞态问题与取消方案-东方仙盟
前端·状态模式·仙盟创梦ide·东方仙盟·网络取消
一级新生10 天前
多智能体协作:常用协作模式详解
人工智能·状态模式·agent·多智能体·智能体