状态模式(State Pattern)
如果任务的执行过程是有多个不同状态的(比如初始化、运行中、完成等),你可以使用状态模式。每个状态可以有不同的行为,使得任务的状态管理更加清晰和可维护。
示例:
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)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,从而让对象看起来像是改变了其类。这种模式非常适合处理对象在不同状态下具有不同行为的场景。
状态模式的核心概念
Context(上下文):
- 包含一个对状态对象的引用,通过这个引用调用状态对象的方法。
- 客户端通过上下文对象与状态对象交互。
State(状态接口):
- 定义了一个接口,用于封装与状态相关的操作。
- 所有具体状态类都实现这个接口。
ConcreteState(具体状态类):
- 实现了状态接口,具体定义了对象在某个状态下的行为。
- 可以访问上下文对象,以便在需要时改变上下文的状态。
示例代码解析
以下是一个完整的状态模式示例,包括上下文类、状态接口和具体状态类。
1. 状态接口(State)
class TaskState {
public:
virtual ~TaskState() {}
virtual void handle(Task* task) = 0; // 处理状态
};
2. 具体状态类(ConcreteState)
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)
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; // 释放状态对象
}
}
};
使用示例
以下是如何使用状态模式来管理任务状态的示例:
#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
状态模式的用途
清晰的状态管理:
- 状态模式将每个状态的行为封装在独立的类中,使得状态管理更加清晰和可维护。
- 每个状态类只关注自己的行为,符合单一职责原则。
动态状态切换:
- 对象可以在运行时动态切换状态,而不需要在上下文类中编写大量的条件语句。
- 状态的切换逻辑由状态类本身管理,减少了上下文类的复杂性。
扩展性:
- 添加新的状态时,只需添加一个新的状态类,而不需要修改现有的上下文类或状态类。
- 符合开闭原则(对扩展开放,对修改封闭)。
与状态观测器的关系
状态模式和状态观测器(Observer Pattern)是两种不同的设计模式,但它们可以结合使用:
状态模式:
- 主要用于管理对象的内部状态和行为。
- 通过状态类的切换来改变对象的行为。
状态观测器(Observer Pattern):
- 主要用于实现对象之间的依赖关系,当一个对象的状态改变时,所有依赖于它的对象都会得到通知并自动更新。
- 适用于多对多的依赖关系,例如事件驱动系统。
结合使用示例
假设你需要在任务状态改变时通知其他对象,可以结合状态模式和状态观测器模式:
定义 Observer 接口:
class Observer { public: virtual void update(const std::string& message) = 0; };
定义 Subject 类:
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); } } };
让 Task 类继承 Subject:
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; } } };
定义具体的 Observer:
class TaskLogger : public Observer { public: void update(const std::string& message) override { std::cout << "Log: " << message << std::endl; } };
使用示例:
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
总结
- 状态模式:用于管理对象的内部状态和行为,通过状态类的切换来改变对象的行为。
- 状态观测器模式:用于实现对象之间的依赖关系,当一个对象的状态改变时,通知所有依赖于它的对象。
- 结合使用:可以通过状态模式管理状态,同时使用状态观测器模式通知其他对象状态的变化。
希望这些解释和示例能帮助你更好地理解状态模式及其用途。