状态模式概述
状态模式是一种行为型设计模式,它可以让一个对象在其内部状态发生变化时更改其行为。通过将每个状态封装成一个独立的类,我们可以使状态之间互相独立,并且使得状态的切换变得更加灵活、可扩展。(多个状态之间可以相互转换)
在状态模式中,我们通常会定义一个抽象状态类(Abstract State),以及多个具体状态类(Concrete States)。每个具体状态都会实现抽象状态类中定义的各种操作,并且在需要时执行状态转换。
此外,还有一个环境类(Context),它包含了当前状态,并且在状态发生变化时调用各个状态类的方法来实现状态转换。因为这些状态类都实现了同一个接口,所以环境类不需要知道具体状态的细节,只需要调用相应的方法即可。
如何理解状态类和环境类
电视遥控器的例子
一个电视遥控器。电视遥控器有三种状态:开机状态、关机状态和静音状态。我们可以通过简单地按遥控器上的按钮来更改状态。为了实现这个功能,首先我们需要定义一个抽象状态类,该类将定义所有可能的操作:
class TVState {
public:
virtual void onButtonPressed(TVRemote* remote) = 0;
virtual void offButtonPressed(TVRemote* remote) = 0;
virtual void muteButtonPressed(TVRemote* remote) = 0;
};
TVState中包含了三种操作:开机、关机和静音。这些操作在不同的状态下可能会有不同的实现方式,因此我们需要在具体状态类中进行实现。
// 具体状态类:开机状态
class OnState : public TVState {
public:
void onButtonPressed(TVRemote* remote) override {
std::cout << "The TV is already on." << std::endl;
}
void offButtonPressed(TVRemote* remote) override {
std::cout << "Turning off the TV." << std::endl;
remote->setState(new OffState());
}
void muteButtonPressed(TVRemote* remote) override {
std::cout << "Muting the TV." << std::endl;
remote->setState(new MuteState());
}
};
// 具体状态类:关机状态
class OffState : public TVState {
public:
void onButtonPressed(TVRemote* remote) override {
std::cout << "Turning on the TV." << std::endl;
remote->setState(new OnState());
}
void offButtonPressed(TVRemote* remote) override {
std::cout << "The TV is already off." << std::endl;
}
void muteButtonPressed(TVRemote* remote) override {
std::cout << "Cannot mute the TV when it's turned off." << std::endl;
}
};
// 具体状态类:静音状态
class MuteState : public TVState {
public:
void onButtonPressed(TVRemote* remote) override {
std::cout << "Unmuting the TV." << std::endl;
remote->setState(new OnState());
}
void offButtonPressed(TVRemote* remote) override {
std::cout << "Turning off the TV." << std::endl;
remote->setState(new OffState());
}
void muteButtonPressed(TVRemote* remote) override {
std::cout << "The TV is already muted." << std::endl;
}
};
在这些具体状态类中,我们重写了TVState中定义的所有操作,并且在需要时执行状态转换。例如,在开机状态下按下静音键会将遥控器的状态更改为“静音状态”。
接下来,让我们定义环境类(Context):
class TVRemote {
private:
TVState* currentState;
public:
TVRemote() {
currentState = new OffState();
}
void setState(TVState* state) {
currentState = state;
}
void pressOnButton() {
currentState->onButtonPressed(this);
}
void pressOffButton() {
currentState->offButtonPressed(this);
}
void pressMuteButton() {
currentState->muteButtonPressed(this);
}
};
在环境类中,我们维护了当前状态,并且在状态发生变化时调用相应的具体状态类方法。我们还定义了三个按键操作:开机、关机和静音。
现在,我们可以使用电视遥控器来测试状态模式的实现了:
int main() {
TVRemote remote;
remote.pressOnButton(); // Turning on the TV.
remote.pressOnButton(); // The TV is already on.
remote.pressMuteButton(); // Muting the TV.
remote.pressMuteButton(); // The TV is already muted.
remote.pressOffButton(); // Turning off the TV.
remote.pressOffButton(); // The TV is already off.
remote.pressMuteButton(); // Cannot mute the TV when it's turned off.
remote.pressOnButton(); // Turning on the TV.
remote.pressMuteButton(); // Unmuting the TV.
return 0;
}
通过上面的代码,我们可以看到当我们按下不同的键时,电视遥控器的状态会发生相应的变化。
完整代码
remote.cpp
#include "remote.h"
#include "state.h"
TVRemote::TVRemote(TVState* State )
{
currentState = State;
}
void TVRemote::setState(TVState* state)
{
currentState = state;
}
void TVRemote::pressOnButton()
{
currentState->onButtonPressed(this);
}
void TVRemote::pressOffButton()
{
currentState->offButtonPressed(this);
}
void TVRemote::pressMuteButton()
{
currentState->muteButtonPressed(this);
}
remote.h
#pragma once
class TVState; //这里没声明,报了一堆错
class TVRemote
{
private:
TVState* currentState;
public:
TVRemote(TVState* State);
void setState(TVState* state);
void pressOnButton();
void pressOffButton();
void pressMuteButton();
};
state.h
#pragma once
#include"remote.h"
class TVState {
public:
virtual void onButtonPressed(TVRemote* remote) = 0; // 开机
virtual void offButtonPressed(TVRemote* remote) = 0; // 关机
virtual void muteButtonPressed(TVRemote* remote) = 0; // 静音
};
// 具体状态类:关机状态
class OffState : public TVState
{
public:
void onButtonPressed(TVRemote* remote) override;
void offButtonPressed(TVRemote* remote) override;
void muteButtonPressed(TVRemote* remote) override;
};
// 具体状态类:开机状态
class OnState : public TVState
{
public:
void onButtonPressed(TVRemote* remote) override;
void offButtonPressed(TVRemote* remote) override;
void muteButtonPressed(TVRemote* remote) override;
};
// 具体状态类:静音状态
class MuteState : public TVState {
public:
void onButtonPressed(TVRemote* remote) override;
void offButtonPressed(TVRemote* remote) override;
void muteButtonPressed(TVRemote* remote) override;
};
state.cpp
#include<iostream>
#include "state.h"
#include "remote.h"
// 具体状态类:关机状态
void OffState::onButtonPressed(TVRemote* remote)
{
std::cout << "Turning on the TV." << std::endl;
remote->setState(new OnState());
}
void OffState::offButtonPressed(TVRemote* remote)
{
std::cout << "The TV is already off." << std::endl;
}
void OffState::muteButtonPressed(TVRemote* remote)
{
std::cout << "Cannot mute the TV when it's turned off." << std::endl;
}
// 具体状态类:开机状态
void OnState::onButtonPressed(TVRemote* remote)
{
std::cout << "The TV is already on." << std::endl;
}
void OnState::offButtonPressed(TVRemote* remote)
{
std::cout << "Turning off the TV." << std::endl;
remote->setState(new OffState());
}
void OnState::muteButtonPressed(TVRemote* remote)
{
std::cout << "Muting the TV." << std::endl;
remote->setState(new MuteState());
}
// 具体状态类:静音状态
void MuteState::onButtonPressed(TVRemote* remote)
{
std::cout << "Unmuting the TV." << std::endl;
remote->setState(new OnState());
}
void MuteState::offButtonPressed(TVRemote* remote)
{
std::cout << "Turning off the TV." << std::endl;
remote->setState(new OffState());
}
void MuteState::muteButtonPressed(TVRemote* remote)
{
std::cout << "The TV is already muted." << std::endl;
}
main.cpp
#include <iostream>
using namespace std;
#include "state.h"
#include "remote.h"
int main() {
TVState* off = new MuteState;
TVRemote remote(off);
remote.pressOnButton(); // Turning on the TV.
remote.pressOnButton(); // The TV is already on.
remote.pressMuteButton(); // Muting the TV.
remote.pressMuteButton(); // The TV is already muted.
remote.pressOffButton(); // Turning off the TV.
remote.pressOffButton(); // The TV is already off.
remote.pressMuteButton(); // Cannot mute the TV when it's turned off.
remote.pressOnButton(); // Turning on the TV.
remote.pressMuteButton(); // Unmuting the TV.
return 0;
}