【GeekBand】C++设计模式笔记18_State_状态模式

1. "状态变化" 模式

  • 在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?"状态变化" 模式为这一问题提供了一种解决方案。
  • 典型模式
    • State
    • Memento

2. State 状态模式

2.1 动机(Motivation)

  • 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能完全不同。
  • 如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?

2.2 模式定义

允许一个对象在其内部状态改变 时改变它的行为。从而使对象看起来似乎修改了其行为。

------《设计模式》GoF

2.3 实例代码

2.3.1 非State模式
cpp 复制代码
enum NetworkState
{
    Network_Open,
    Network_Close,
    Network_Connect,
};


class NetworkProcessor {
    
    NetworkState state;

public:
    
    void Operation1() {
        if (state == Network_Open) {

            //**********
            state = Network_Close;		// 改变状态值
        }
        else if (state == Network_Close) {

            //..........
            state = Network_Connect;
        }
        else if (state == Network_Connect) {

            //$$$$$$$$$$
            state = Network_Open;
        }
    }

    public void Operation2() {
        if (state == Network_Open) {
            
            //**********
            state = Network_Connect;
        }
        else if (state == Network_Close) {

            //.....
            state = Network_Open;
        }
        else if (state == Network_Connect) {

            //$$$$$$$$$$
            state = Network_Close;
        }    
    }

    public void Operation3() {

    }
};

非State模式代码中的类方法中充斥着大量的if分支语句来判断状态的值,从而采取对应的操作,显得很臃肿;而且,当添加一个新状态时,需要在所有的if条件判断语句中添加新的分支。

2.3.2 State模式
cpp 复制代码
// 状态的抽象类
class NetworkState {

public:
    NetworkState* pNext;	// 下一个状态值
    
    virtual void Operation1() = 0;
    virtual void Operation2() = 0;
    virtual void Operation3() = 0;

    virtual ~NetworkState() {}
};

// 继承,实现抽象接口
class OpenState: public NetworkState {
    static NetworkState* m_instance;	// 当前状态属性值
    
public:
	// 单例模式
    static NetworkState* getInstance() {
        if (m_instance == nullptr) {
            m_instance = new OpenState();
        }
        
        return m_instance;
    }

    void Operation1() {
        
        //**********
        pNext = CloseState::getInstance();	// 下一个状态值
    }
    
    void Operation2() {
        
        //..........
        pNext = ConnectState::getInstance();
    }
    
    void Operation3() {
        
        //$$$$$$$$$$
        pNext = OpenState::getInstance();
    }
};

// 代码类似OpenState
class CloseState: public NetworkState { }

// 扩展新状态
//...


class NetworkProcessor { 
    NetworkState* pState;
    
public:
    // 构造函数中传入初始状态值
    NetworkProcessor(NetworkState* pState) {
        this->pState = pState;
    }
    
    void Operation1() {
        //...
        pState->Operation1();
        pState = pState->pNext;	// 将当前状态值切换为下一个状态
        //...
    }
    
    void Operation2() {
        //...
        pState->Operation2();
        pState = pState->pNext;
        //...
    }
    
    void Operation3() {
        //...
        pState->Operation3();
        pState = pState->pNext;
        //...
    }
};

State模式代码中去除了大量的if条件判断分支,将每个状态用一个单独的状态子类来表示,且将与具体状态相关的操作放在子类中。在实际应用中,接口保持不变,利用多态特性,根据状态的真实值从而调用对应的方法。

2.4 结构(Structure)

2.5 要点总结

  • State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态切换之间的解耦。
  • 为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子的------即要么彻底转换过来,要么不转换。
  • 如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。
相关推荐
Zhichao_9731 分钟前
【UE5 C++课程系列笔记】33——商业化Json读写
c++·ue5
云边有个稻草人1 小时前
【C++】第八节—string类(上)——详解+代码示例
开发语言·c++·迭代器·string类·语法糖auto和范围for·string类的常用接口·operator[]
惊鸿一博1 小时前
c++ &&(通用引用)和&(左值引用)区别
开发语言·c++
高 朗2 小时前
2025高频面试设计模型总结篇
设计模式·面试·职场和发展
nuo5342022 小时前
黑马 C++ 学习笔记
c语言·c++·笔记·学习
DARLING Zero two♡2 小时前
C++类间的 “接力棒“ 传递:继承(上)
开发语言·c++·继承·里氏替换原则
会讲英语的码农2 小时前
如何学习C++以及C++的宏观认知
开发语言·c++·学习
Merokes10 小时前
关于Gstreamer+MPP硬件加速推流问题:视频输入video0被占用
c++·音视频·rk3588
请来次降维打击!!!11 小时前
优选算法系列(5.位运算)
java·前端·c++·算法
别NULL11 小时前
机试题——统计最少媒体包发送源个数
c++·算法·媒体