👨🎓 模式名称:状态模式(State)
👦 故事背景:
👦 小明在他的平台引入了外卖骑手系统,其中就需要及时记录和更新骑手的状态。骑手的状态分为:
- 待接单
- 配送中
- 休息中
不同状态下,系统允许执行的操作不同:
| 状态 | 允许操作 |
|---|---|
| 待接单 | 可以接单 |
| 配送中 | 可以送达 |
| 休息中 | 什么都不能做 |
😵 不使用状态模式的痛点
小明一开始直接用了一个大 switch-case 写法:
cpp
enum RiderState { Idle, Delivering, Resting };
class Rider {
public:
RiderState state;
void handle(const std::string& action) {
if (state == Idle) {
if (action == "接单") std::cout << "订单接下来了!" << std::endl;
else std::cout << "当前不能 " << action << std::endl;
} else if (state == Delivering) {
if (action == "送达") std::cout << "订单已送达!" << std::endl;
else std::cout << "当前不能 " << action << std::endl;
} else if (state == Resting) {
std::cout << "休息中,啥也不能干..." << std::endl;
}
}
};
问题来了:
- 每次加新状态或行为,都要修改 handle 函数
- 状态行为之间 耦合严重
- 系统难以扩展和维护
✅ 使用状态模式进行优化
1️⃣ 状态接口(抽象状态类)
cpp
class RiderContext;
class RiderState {
public:
virtual void handle(RiderContext* context, const std::string& action) = 0;
virtual std::string name() const = 0;
virtual ~RiderState() {}
};
2️⃣ 具体状态类
cpp
class IdleState : public RiderState {
public:
void handle(RiderContext* context, const std::string& action) override;
std::string name() const override { return "待接单"; }
};
class DeliveringState : public RiderState {
public:
void handle(RiderContext* context, const std::string& action) override;
std::string name() const override { return "配送中"; }
};
class RestingState : public RiderState {
public:
void handle(RiderContext* context, const std::string& action) override;
std::string name() const override { return "休息中"; }
};
3️⃣ 状态上下文类
cpp
class RiderContext {
private:
RiderState* state;
public:
RiderContext(RiderState* init) : state(init) {}
void setState(RiderState* s) {
state = s;
std::cout << "状态切换为:" << state->name() << std::endl;
}
void request(const std::string& action) {
state->handle(this, action);
}
};
4️⃣ 状态行为实现
cpp
void IdleState::handle(RiderContext* context, const std::string& action) {
if (action == "接单") {
std::cout << "✅ 订单已接下!" << std::endl;
static DeliveringState delivering;
context->setState(&delivering);
} else {
std::cout << "❌ 当前状态不能执行:" << action << std::endl;
}
}
void DeliveringState::handle(RiderContext* context, const std::string& action) {
if (action == "送达") {
std::cout << "✅ 外卖已送达!" << std::endl;
static IdleState idle;
context->setState(&idle);
} else {
std::cout << "❌ 当前状态不能执行:" << action << std::endl;
}
}
void RestingState::handle(RiderContext* context, const std::string& action) {
std::cout << "😴 休息中,不能进行任何操作..." << std::endl;
}
使用示例
cpp
int main() {
IdleState idle;
RiderContext rider(&idle);
rider.request("接单");
rider.request("送达");
static RestingState rest;
rider.setState(&rest);
rider.request("接单");
}
使用状态模式的优点
| 问题 | 是否解决 |
|---|---|
| 状态逻辑封装 ✅ | 各状态类独立处理自己的逻辑 |
| 行为扩展方便 ✅ | 新状态只需添加类,无需修改已有逻辑 |
| 状态切换明确 ✅ | 使用 setState 清晰过渡 |
| 可复用性提升 ✅ | 各状态类可在其他场景复用 |