状态模式(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

总结

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

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

相关推荐
PPPPickup2 小时前
easymall----管理后端分类展示
状态模式
前端不太难5 小时前
HarmonyOS 游戏运行态的完整状态机图
游戏·状态模式·harmonyos
前端不太难1 天前
HarmonyOS 为何用 Ability 约束游戏?
游戏·状态模式·harmonyos
新缸中之脑1 天前
5个AI设计的音乐 UI 比较
人工智能·ui·状态模式
前端不太难1 天前
游戏在 HarmonyOS 上如何“活”?
游戏·状态模式·harmonyos
浮游本尊2 天前
React 18.x 学习计划 - 第十三天:部署与DevOps实践
学习·react.js·状态模式
Vv1997_2 天前
JavaWeb后端全局异常处理
状态模式
小郎君。2 天前
PDF-知识图谱全流程前后端实现【工具已实现,搭建前后端pipline】
pdf·状态模式·知识图谱
前端不太难2 天前
HarmonyOS PC 焦点系统的正确建模方式
华为·状态模式·harmonyos
前端不太难2 天前
HarmonyOS PC 如何应对多输入交互?
状态模式·交互·harmonyos