状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为。状态模式将状态的相关行为封装到独立的状态类中,并通过在这些状态类之间切换来改变对象的行为。这样可以使状态转换变得更加明确和易于管理。
实际应用场景
假设我们有一个简单的电梯控制系统。电梯可以处于不同的状态,例如停止、向上移动、向下移动。每种状态下,电梯的行为是不同的。我们可以使用状态模式来管理电梯的这些状态和行为。
代码示例
下面是一个使用状态模式实现电梯控制系统的示例代码:
1. 定义状态接口
首先,我们定义一个表示电梯状态的接口 ElevatorState
,该接口包含电梯在不同状态下的行为方法。
#include <iostream>
#include <memory>
// 电梯状态接口
class ElevatorState {
public:
virtual ~ElevatorState() = default;
virtual void moveUp() = 0;
virtual void moveDown() = 0;
virtual void stop() = 0;
};
class ElevatorContext; // 前向声明
2. 定义具体状态类
然后,我们定义具体的状态类,例如 MovingUpState
、MovingDownState
和 StoppedState
,每个状态类实现 ElevatorState
接口。
class MovingUpState : public ElevatorState {
public:
explicit MovingUpState(ElevatorContext* context) : context_(context) {}
void moveUp() override {
std::cout << "Already moving up." << std::endl;
}
void moveDown() override {
std::cout << "Cannot move down while moving up." << std::endl;
}
void stop() override;
private:
ElevatorContext* context_;
};
class MovingDownState : public ElevatorState {
public:
explicit MovingDownState(ElevatorContext* context) : context_(context) {}
void moveUp() override {
std::cout << "Cannot move up while moving down." << std::endl;
}
void moveDown() override {
std::cout << "Already moving down." << std::endl;
}
void stop() override;
private:
ElevatorContext* context_;
};
class StoppedState : public ElevatorState {
public:
explicit StoppedState(ElevatorContext* context) : context_(context) {}
void moveUp() override;
void moveDown() override;
void stop() override {
std::cout << "Already stopped." << std::endl;
}
private:
ElevatorContext* context_;
};
3. 定义电梯上下文类
接下来,我们定义一个电梯上下文类 ElevatorContext
,它持有当前状态的实例,并提供改变状态的方法。
class ElevatorContext {
public:
ElevatorContext() : state_(std::make_unique<StoppedState>(this)) {}
void setState(std::unique_ptr<ElevatorState> state) {
state_ = std::move(state);
}
void moveUp() {
state_->moveUp();
}
void moveDown() {
state_->moveDown();
}
void stop() {
state_->stop();
}
private:
std::unique_ptr<ElevatorState> state_;
};
4. 实现状态转换
最后,我们在具体状态类中实现状态转换的方法。
void MovingUpState::stop() {
std::cout << "Stopping from moving up." << std::endl;
context_->setState(std::make_unique<StoppedState>(context_));
}
void MovingDownState::stop() {
std::cout << "Stopping from moving down." << std::endl;
context_->setState(std::make_unique<StoppedState>(context_));
}
void StoppedState::moveUp() {
std::cout << "Starting to move up." << std::endl;
context_->setState(std::make_unique<MovingUpState>(context_));
}
void StoppedState::moveDown() {
std::cout << "Starting to move down." << std::endl;
context_->setState(std::make_unique<MovingDownState>(context_));
}
5. 使用示例
int main() {
ElevatorContext elevator;
// 电梯从停止状态开始
elevator.moveUp(); // 输出: Starting to move up.
elevator.moveUp(); // 输出: Already moving up.
elevator.stop(); // 输出: Stopping from moving up.
elevator.moveDown(); // 输出: Starting to move down.
elevator.stop(); // 输出: Stopping from moving down.
elevator.moveDown(); // 输出: Starting to move down.
return 0;
}
完整代码
#include <iostream>
#include <memory>
// 电梯状态接口
class ElevatorState {
public:
virtual ~ElevatorState() = default;
virtual void moveUp() = 0;
virtual void moveDown() = 0;
virtual void stop() = 0;
};
class ElevatorContext; // 前向声明
class MovingUpState : public ElevatorState {
public:
explicit MovingUpState(ElevatorContext* context) : context_(context) {}
void moveUp() override {
std::cout << "Already moving up." << std::endl;
}
void moveDown() override {
std::cout << "Cannot move down while moving up." << std::endl;
}
void stop() override;
private:
ElevatorContext* context_;
};
class MovingDownState : public ElevatorState {
public:
explicit MovingDownState(ElevatorContext* context) : context_(context) {}
void moveUp() override {
std::cout << "Cannot move up while moving down." << std::endl;
}
void moveDown() override {
std::cout << "Already moving down." << std::endl;
}
void stop() override;
private:
ElevatorContext* context_;
};
class StoppedState : public ElevatorState {
public:
explicit StoppedState(ElevatorContext* context) : context_(context) {}
void moveUp() override;
void moveDown() override;
void stop() override {
std::cout << "Already stopped." << std::endl;
}
private:
ElevatorContext* context_;
};
class ElevatorContext {
public:
ElevatorContext() : state_(std::make_unique<StoppedState>(this)) {}
void setState(std::unique_ptr<ElevatorState> state) {
state_ = std::move(state);
}
void moveUp() {
state_->moveUp();
}
void moveDown() {
state_->moveDown();
}
void stop() {
state_->stop();
}
private:
std::unique_ptr<ElevatorState> state_;
};
void MovingUpState::stop() {
std::cout << "Stopping from moving up." << std::endl;
context_->setState(std::make_unique<StoppedState>(context_));
}
void MovingDownState::stop() {
std::cout << "Stopping from moving down." << std::endl;
context_->setState(std::make_unique<StoppedState>(context_));
}
void StoppedState::moveUp() {
std::cout << "Starting to move up." << std::endl;
context_->setState(std::make_unique<MovingUpState>(context_));
}
void StoppedState::moveDown() {
std::cout << "Starting to move down." << std::endl;
context_->setState(std::make_unique<MovingDownState>(context_));
}
int main() {
ElevatorContext elevator;
// 电梯从停止状态开始
elevator.moveUp(); // 输出: Starting to move up.
elevator.moveUp(); // 输出: Already moving up.
elevator.stop(); // 输出: Stopping from moving up.
elevator.moveDown(); // 输出: Starting to move down.
elevator.stop(); // 输出: Stopping from moving down.
elevator.moveDown(); // 输出: Starting to move down.
return 0;
}
总结
在这个示例中,我们使用状态模式将电梯的不同状态(停止、向上移动、向下移动)封装到独立的状态类中。电梯上下文类 ElevatorContext
持有当前状态的实例,并通过调用状态对象的方法来改变电梯的行为和状态。这使得状态转换变得更加明确和易于管理,同时也提高了代码的可维护性和可扩展性。