• 【30】c++设计模式——>状态模式


    状态模式概述

    状态模式是一种行为型设计模式,它可以让一个对象在其内部状态发生变化时更改其行为。通过将每个状态封装成一个独立的类,我们可以使状态之间互相独立,并且使得状态的切换变得更加灵活、可扩展。(多个状态之间可以相互转换)
    在状态模式中,我们通常会定义一个抽象状态类(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;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    在这些具体状态类中,我们重写了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);
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在环境类中,我们维护了当前状态,并且在状态发生变化时调用相应的具体状态类方法。我们还定义了三个按键操作:开机、关机和静音。
    现在,我们可以使用电视遥控器来测试状态模式的实现了:

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    通过上面的代码,我们可以看到当我们按下不同的键时,电视遥控器的状态会发生相应的变化。

    完整代码

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    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;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    state.cpp

    #include
    #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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    main.cpp

    #include 
    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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述

  • 相关阅读:
    算法基础——求每对结点之间的最短路径
    分析-BeanPostProceesor后置处理器
    C++中内存泄漏和智能指针
    vue学习笔记——简单入门总结(三)
    Django对接支付宝Alipay支付接口
    赶快收藏不迷路,不允许你还不知道这几个程序员接单平台!!!
    html网页设计模板制作前需要准备什么?
    计算机毕设(附源码)JAVA-SSM基于的小型房屋租赁平台
    Windows系统创建Python虚拟环境
    从零到一部署网站(一)
  • 原文地址:https://blog.csdn.net/weixin_42097108/article/details/133986607