【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对象,从而节省对象开销。
相关推荐
敷啊敷衍17 分钟前
深入探索 C++ 中的 string 类:从基础到实践
开发语言·数据结构·c++
什么名字都被用了39 分钟前
编译openssl源码
c++·openssl
ai.Neo1 小时前
牛客网NC22157:牛牛学数列2
数据结构·c++·算法
Nobkins2 小时前
2023CCPC河南省赛暨河南邀请赛个人补题ABEFGHK
开发语言·数据结构·c++·算法·图论
珊瑚里的鱼2 小时前
第九讲 | 模板进阶
开发语言·c++·笔记·visualstudio·学习方法·visual studio
摄殓永恒3 小时前
猫咪几岁
数据结构·c++·算法
.小墨迹4 小时前
Apollo学习——键盘控制速度
linux·开发语言·c++·python·学习·计算机外设
似水এ᭄往昔4 小时前
【数据结构】——队列
c语言·数据结构·c++·链表
烛九_阴4 小时前
【C++】解析C++面向对象三要素:封装、继承与多态实现机制
c++
ai.Neo5 小时前
牛客网NC22012:判断闰年问题详解
开发语言·c++·算法