1、状态模式概述:
状态模式(State Pattern)是一种行为设计模式,允许一个对象在其内部状态改变时改变它的行为。这种模式通过将状态抽象为一个独立的类,并通过在原始对象中维护一个对当前状态对象的引用来实现。通过改变原始对象所引用的状态对象,我们可以动态地改变原始对象的行为。
2、状态模式的适用场景:
- 当一个对象的行为取决于其状态,并且它在运行时可能需要根据状态改变行为时。
- 当一个对象的操作中包含大量与状态相关的条件语句,导致代码难以维护和扩展时。状态模式可以将这些条件语句分散到各个状态类中,使得代码更易于维护和扩展。
3、状态模式的优点:
- 状态模式将与特定状态相关的行为局部化到各自的状态类中,提高了代码的可读性和可维护性。
- 状态模式通过将状态转换为独立的对象,提高了代码的可扩展性。添加新的状态或修改现有状态不会影响到其他状态类或原始对象。
- 状态模式可以消除大量的条件语句,简化了代码结构。
举例说明:假设我们有一个音频播放器,它可以有多种状态(如播放、暂停、停止等)。通过使用状态模式,我们可以将与播放器状态相关的行为分散到各个状态类中。这样,如果我们需要添加新的状态(例如“快进”),只需要创建一个新的状态类,而不需要修改播放器类或其他状态类。
4、状态模式的缺点:
- 状态模式可能会导致类数量的增加,因为每个状态都需要一个对应的类。这可能会导致系统变得更加复杂。
- 状态模式的实现通常需要更多的间接性,这可能会导致性能上的损失。
举例说明:在上面的音频播放器示例中,如果有许多状态,我们可能需要为每个状态创建一个单独的类。这将导致类数量的增加,使得系统更加复杂。此外,播放器类需要维护对当前状态对象的引用,这可能会导致一些性能损失。
5、用C++实现一个状态模式例子:
#include <iostream>
#include <memory>
// 抽象状态类
class AudioPlayer;
class State {
public:
virtual ~State() = default;
virtual void play(AudioPlayer &player) = 0;
virtual void pause(AudioPlayer &player) = 0;
virtual void stop(AudioPlayer &player) = 0;
};
// 具体状态类
class PlayingState : public State {
public:
void play(AudioPlayer &player) override;
void pause(AudioPlayer &player) override;
void stop(AudioPlayer &player) override;
};
class PausedState : public State {
public:
void play(AudioPlayer &player) override;
void pause(AudioPlayer &player) override;
void stop(AudioPlayer &player) override;
};
class StoppedState : public State {
public:
void play(AudioPlayer &player) override;
void pause(AudioPlayer &player) override;
void stop(AudioPlayer &player) override;
};
// 音频播放器
class AudioPlayer {
public:
AudioPlayer() : state(std::make_shared<StoppedState>()) {}
void play() {
state->play(*this);
}
void pause() {
state->pause(*this);
}
void stop() {
state->stop(*this);
}
void changeState(std::shared_ptr<State> newState) {
state = newState;
}
private:
std::shared_ptr<State> state;
};
// 具体状态类实现
void PlayingState::play(AudioPlayer &player) {
std::cout << "Already playing" << std::endl;
}
void PlayingState::pause(AudioPlayer &player) {
std::cout << "Pausing" << std::endl;
player.changeState(std::make_shared<PausedState>());
}
void PlayingState::stop(AudioPlayer &player) {
std::cout << "Stopping" << std::endl;
player.changeState(std::make_shared<StoppedState>());
}
void PausedState::play(AudioPlayer &player) {
std::cout << "Resuming" << std::endl;
player.changeState(std::make_shared<PlayingState>());
}
void PausedState::pause(AudioPlayer &player) {
std::cout << "Already paused" << std::endl;
}
void PausedState::stop(AudioPlayer &player) {
std::cout << "Stopping" << std::endl;
player.changeState(std::make_shared<StoppedState>());
}
void StoppedState::play(AudioPlayer &player) {
std::cout << "Starting to play" << std::endl;
player.changeState(std::make_shared<PlayingState>());
}
void StoppedState::pause(AudioPlayer &player) {
std::cout << "Can't pause, already stopped" << std::endl;
}
void StoppedState::stop(AudioPlayer &player) {
std::cout << "Already stopped" << std::endl;
}
int main() {
AudioPlayer player;
player.play();
player.pause();
player.play();
player.stop();
return 0;
}
在这个示例中,我们定义了一个抽象的状态类 State 和三个具体的状态类:PlayingState、PausedState 和 StoppedState。每个具体的状态类都实现了抽象状态类中的 play()、pause() 和 stop() 方法。音频播放器 AudioPlayer 类包含一个当前状态成员变量 state。通过调用 changeState() 方法,我们可以在不同的状态之间进行切换。在每个具体状态类的实现中,我们根据播放器当前的状态,执行相应的操作并可能更改播放器的状态。例如,在 PlayingState 中调用 pause() 方法时,播放器会转到 PausedState 状态。
这个示例展示了如何使用状态模式来管理一个音频播放器的状态。通过将状态与音频播放器分离,我们可以更轻松地管理和扩展播放器的行为。此外,我们遵循了单一职责原则,使得每个状态类只关注与自身相关的行为。