【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对象,从而节省对象开销。
相关推荐
2301_807611491 小时前
77. 组合
c++·算法·leetcode·深度优先·回溯
微网兔子2 小时前
伺服器用什么语言开发呢?做什么用什么?
服务器·c++·后端·游戏
YuforiaCode2 小时前
第十三届蓝桥杯 2022 C/C++组 修剪灌木
c语言·c++·蓝桥杯
YOULANSHENGMENG2 小时前
linux 下python 调用c++的动态库的方法
c++·python
CodeWithMe2 小时前
【C++】STL之deque
开发语言·c++
炯哈哈3 小时前
【上位机——MFC】运行时类信息机制
开发语言·c++·mfc·上位机
rigidwill6664 小时前
LeetCode hot 100—最长有效括号
数据结构·c++·算法·leetcode·职场和发展
阳光_你好4 小时前
C++/Qt中QActionGroup类用法
c++·qt
周努力.5 小时前
设计模式之策略模式
设计模式·策略模式
菜鸟射手5 小时前
QT creater和vs2017文件路径问题
linux·c++·windows·qt