C++中的状态模式

目录

[状态模式(State Pattern)](#状态模式(State Pattern))

实际应用

停车收费系统

音乐播放器的播放状态

电梯控制系统

总结


状态模式(State Pattern)

状态模式是一种行为型设计模式,它允许对象在其内部状态改变时改变其行为。这种模式可以避免在对象中使用大量的条件语句,从而使我们开发的代码更加清晰和易于维护。

状态模式主要包含以下角色:

  1. Context (上下文):定义客户感兴趣的接口,并且维护一个ConcreteState 子类的实例,这个实例定义当前状态。

  2. State (状态):定义一个接口以封装与Context 的一个特定状态相关的行为。

  3. ConcreteState (具体状态):每一个具体状态类实现了State接口。

实际应用

停车收费系统

-- 实现一个停车收费系统,根据停车时间计算费用,不同的时间段有不同的收费标准。

cpp 复制代码
#include <iostream>
#include <memory>

// 上下文类
class ParkingMeter;

// 状态接口类
class ParkingState {
public:
    virtual void enterTime(ParkingMeter* meter, int minutes) = 0;
    virtual void calculateFee(ParkingMeter* meter) = 0;
};

// 上下文类
class ParkingMeter {
private:
    std::unique_ptr<ParkingState> state;
    int totalMinutes;
    double fee;

public:
    ParkingMeter();
    void setState(std::unique_ptr<ParkingState> newState);
    void addTime(int minutes);
    void calculateFee();
    int getTotalMinutes() const;
    void setFee(double newFee);
    double getFee() const;
};

// 具体状态类:免费时间段
class FreeState : public ParkingState {
public:
    void enterTime(ParkingMeter* meter, int minutes) override;
    void calculateFee(ParkingMeter* meter) override;
};

// 具体状态类:收费时间段
class PaidState : public ParkingState {
public:
    void enterTime(ParkingMeter* meter, int minutes) override;
    void calculateFee(ParkingMeter* meter) override;
};

// ParkingMeter方法的实现
ParkingMeter::ParkingMeter() : totalMinutes(0), fee(0.0) {
    state = std::make_unique<FreeState>();
}

void ParkingMeter::setState(std::unique_ptr<ParkingState> newState) {
    state = std::move(newState);
}

void ParkingMeter::addTime(int minutes) {
    state->enterTime(this, minutes);
}

void ParkingMeter::calculateFee() {
    state->calculateFee(this);
}

int ParkingMeter::getTotalMinutes() const {
    return totalMinutes;
}

void ParkingMeter::setFee(double newFee) {
    fee = newFee;
}

double ParkingMeter::getFee() const {
    return fee;
}

// FreeState方法的实现
void FreeState::enterTime(ParkingMeter* meter, int minutes) {
    int newTotalMinutes = meter->getTotalMinutes() + minutes;
    meter->setFee(0.0); // 免费时间段,费用为0

    if (newTotalMinutes > 60) {
        // 超过60分钟,进入收费时间段
        meter->setState(std::make_unique<PaidState>());
        meter->addTime(newTotalMinutes - 60);
    } else {
        // 在免费时间段内
        std::cout << "Time entered: " << minutes << " minutes. Total time: " << newTotalMinutes << " minutes." << std::endl;
    }
}

void FreeState::calculateFee(ParkingMeter* meter) {
    std::cout << "Total parking fee: $" << meter->getFee() << " (Free period)" << std::endl;
}

// PaidState方法的实现
void PaidState::enterTime(ParkingMeter* meter, int minutes) {
    int newTotalMinutes = meter->getTotalMinutes() + minutes;
    meter->setFee(newTotalMinutes * 0.5); // 收费时间段,每分钟0.5美元

    std::cout << "Time entered: " << minutes << " minutes. Total time: " << newTotalMinutes << " minutes." << std::endl;
}

void PaidState::calculateFee(ParkingMeter* meter) {
    std::cout << "Total parking fee: $" << meter->getFee() << " (Paid period)" << std::endl;
}

// 客户端代码
int main() {
    ParkingMeter meter;
    meter.addTime(30); // 免费时间段
    meter.calculateFee();

    meter.addTime(40); // 转入收费时间段
    meter.calculateFee();

    meter.addTime(20); // 收费时间段
    meter.calculateFee();

    return 0;
}

音乐播放器的播放状态

-- 实现一个音乐播放器,可以在播放、暂停和停止状态之间切换。

cpp 复制代码
#include <iostream>
#include <memory>
#include <string>

// 上下文类
class MusicPlayer;

// 状态接口类
class PlayerState {
public:
    virtual void play(MusicPlayer* player) = 0;
    virtual void pause(MusicPlayer* player) = 0;
    virtual void stop(MusicPlayer* player) = 0;
};

// 上下文类
class MusicPlayer {
private:
    std::unique_ptr<PlayerState> state;
    std::string currentTrack;

public:
    MusicPlayer();
    void setState(std::unique_ptr<PlayerState> newState);
    void play();
    void pause();
    void stop();
    void setTrack(const std::string& track);
    std::string getTrack() const;
};

// 具体状态类:播放状态
class PlayingState : public PlayerState {
public:
    void play(MusicPlayer* player) override;
    void pause(MusicPlayer* player) override;
    void stop(MusicPlayer* player) override;
};

// 具体状态类:暂停状态
class PausedState : public PlayerState {
public:
    void play(MusicPlayer* player) override;
    void pause(MusicPlayer* player) override;
    void stop(MusicPlayer* player) override;
};

// 具体状态类:停止状态
class StoppedState : public PlayerState {
public:
    void play(MusicPlayer* player) override;
    void pause(MusicPlayer* player) override;
    void stop(MusicPlayer* player) override;
};

// MusicPlayer方法的实现
MusicPlayer::MusicPlayer() {
    state = std::make_unique<StoppedState>();
}

void MusicPlayer::setState(std::unique_ptr<PlayerState> newState) {
    state = std::move(newState);
}

void MusicPlayer::play() {
    state->play(this);
}

void MusicPlayer::pause() {
    state->pause(this);
}

void MusicPlayer::stop() {
    state->stop(this);
}

void MusicPlayer::setTrack(const std::string& track) {
    currentTrack = track;
}

std::string MusicPlayer::getTrack() const {
    return currentTrack;
}

// PlayingState方法的实现
void PlayingState::play(MusicPlayer* player) {
    std::cout << "Already playing " << player->getTrack() << std::endl;
}

void PlayingState::pause(MusicPlayer* player) {
    std::cout << "Pausing " << player->getTrack() << std::endl;
    player->setState(std::make_unique<PausedState>());
}

void PlayingState::stop(MusicPlayer* player) {
    std::cout << "Stopping " << player->getTrack() << std::endl;
    player->setState(std::make_unique<StoppedState>());
}

// PausedState方法的实现
void PausedState::play(MusicPlayer* player) {
    std::cout << "Resuming " << player->getTrack() << std::endl;
    player->setState(std::make_unique<PlayingState>());
}

void PausedState::pause(MusicPlayer* player) {
    std::cout << "Already paused " << player->getTrack() << std::endl;
}

void PausedState::stop(MusicPlayer* player) {
    std::cout << "Stopping " << player->getTrack() << std::endl;
    player->setState(std::make_unique<StoppedState>());
}

// StoppedState方法的实现
void StoppedState::play(MusicPlayer* player) {
    std::cout << "Playing " << player->getTrack() << std::endl;
    player->setState(std::make_unique<PlayingState>());
}

void StoppedState::pause(MusicPlayer* player) {
    std::cout << "Cannot pause, " << player->getTrack() << " is not playing" << std::endl;
}

void StoppedState::stop(MusicPlayer* player) {
    std::cout << "Already stopped " << player->getTrack() << std::endl;
}

// 客户端代码
int main() {
    MusicPlayer player;
    player.setTrack("Song A");

    player.play(); // Playing Song A
    player.pause(); // Pausing Song A
    player.play(); // Resuming Song A
    player.stop(); // Stopping Song A

    player.setTrack("Song B");
    player.play(); // Playing Song B
    player.stop(); // Stopping Song B
    player.pause(); // Cannot pause, Song B is not playing

    return 0;
}

电梯控制系统

-- 实现一个电梯控制系统,电梯有多种状态,如运行状态、停止状态和维护状态。

cpp 复制代码
#include <iostream>
#include <memory>
#include <string>

// 上下文类
class Elevator;

// 状态接口类
class ElevatorState {
public:
    virtual void goUp(Elevator* elevator) = 0;
    virtual void goDown(Elevator* elevator) = 0;
    virtual void stop(Elevator* elevator) = 0;
    virtual void maintain(Elevator* elevator) = 0;
};

// 上下文类
class Elevator {
private:
    std::unique_ptr<ElevatorState> state;

public:
    Elevator();
    void setState(std::unique_ptr<ElevatorState> newState);
    void goUp();
    void goDown();
    void stop();
    void maintain();
};

// 具体状态类:运行状态
class RunningState : public ElevatorState {
public:
    void goUp(Elevator* elevator) override;
    void goDown(Elevator* elevator) override;
    void stop(Elevator* elevator) override;
    void maintain(Elevator* elevator) override;
};

// 具体状态类:停止状态
class StoppedState : public ElevatorState {
public:
    void goUp(Elevator* elevator) override;
    void goDown(Elevator* elevator) override;
    void stop(Elevator* elevator) override;
    void maintain(Elevator* elevator) override;
};

// 具体状态类:维护状态
class MaintenanceState : public ElevatorState {
public:
    void goUp(Elevator* elevator) override;
    void goDown(Elevator* elevator) override;
    void stop(Elevator* elevator) override;
    void maintain(Elevator* elevator) override;
};

// Elevator方法的实现
Elevator::Elevator() {
    state = std::make_unique<StoppedState>();
}

void Elevator::setState(std::unique_ptr<ElevatorState> newState) {
    state = std::move(newState);
}

void Elevator::goUp() {
    state->goUp(this);
}

void Elevator::goDown() {
    state->goDown(this);
}

void Elevator::stop() {
    state->stop(this);
}

void Elevator::maintain() {
    state->maintain(this);
}

// RunningState方法的实现
void RunningState::goUp(Elevator* elevator) {
    std::cout << "The elevator is already running upward." << std::endl;
}

void RunningState::goDown(Elevator* elevator) {
    std::cout << "The elevator is already running downward." << std::endl;
}

void RunningState::stop(Elevator* elevator) {
    std::cout << "Stopping the elevator." << std::endl;
    elevator->setState(std::make_unique<StoppedState>());
}

void RunningState::maintain(Elevator* elevator) {
    std::cout << "Cannot enter maintenance mode while running." << std::endl;
}

// StoppedState方法的实现
void StoppedState::goUp(Elevator* elevator) {
    std::cout << "The elevator is going up." << std::endl;
    elevator->setState(std::make_unique<RunningState>());
}

void StoppedState::goDown(Elevator* elevator) {
    std::cout << "The elevator is going down." << std::endl;
    elevator->setState(std::make_unique<RunningState>());
}

void StoppedState::stop(Elevator* elevator) {
    std::cout << "The elevator is already stopped." << std::endl;
}

void StoppedState::maintain(Elevator* elevator) {
    std::cout << "Entering maintenance mode." << std::endl;
    elevator->setState(std::make_unique<MaintenanceState>());
}

// MaintenanceState方法的实现
void MaintenanceState::goUp(Elevator* elevator) {
    std::cout << "Cannot go up while in maintenance mode." << std::endl;
}

void MaintenanceState::goDown(Elevator* elevator) {
    std::cout << "Cannot go down while in maintenance mode." << std::endl;
}

void MaintenanceState::stop(Elevator* elevator) {
    std::cout << "Cannot stop while in maintenance mode." << std::endl;
}

void MaintenanceState::maintain(Elevator* elevator) {
    std::cout << "Already in maintenance mode." << std::endl;
}

// 客户端代码
int main() {
    Elevator elevator;

    elevator.goUp(); // The elevator is going up.
    elevator.stop(); // Stopping the elevator.
    elevator.maintain(); // Entering maintenance mode.
    elevator.goUp(); // Cannot go up while in maintenance mode.
    elevator.stop(); // Cannot stop while in maintenance mode.

    elevator.setState(std::make_unique<StoppedState>()); // Simulate exiting maintenance
    elevator.goDown(); // The elevator is going down.
    elevator.stop(); // Stopping the elevator.

    return 0;
}

总结

状态模式通过将状态转换逻辑从上下文类中抽离出来,使代码更加清晰和易于维护。

相关推荐
无 证明21 分钟前
new 分配空间;引用
数据结构·c++
Kisorge44 分钟前
【C语言】指针数组、数组指针、函数指针、指针函数、函数指针数组、回调函数
c语言·开发语言
轻口味2 小时前
命名空间与模块化概述
开发语言·前端·javascript
晓纪同学3 小时前
QT-简单视觉框架代码
开发语言·qt
威桑3 小时前
Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
开发语言·qt·扩张策略
飞飞-躺着更舒服3 小时前
【QT】实现电子飞行显示器(简易版)
开发语言·qt
明月看潮生3 小时前
青少年编程与数学 02-004 Go语言Web编程 16课题、并发编程
开发语言·青少年编程·并发编程·编程与数学·goweb
明月看潮生3 小时前
青少年编程与数学 02-004 Go语言Web编程 17课题、静态文件
开发语言·青少年编程·编程与数学·goweb
Java Fans3 小时前
C# 中串口读取问题及解决方案
开发语言·c#
盛派网络小助手3 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#