[A].总结7.状态变化:状态模式,备忘录

总结7.状态变化:状态模式,备忘录

声明:本栏目的 [A] 系列的学习笔记,学习对象为 B 站授课视频 C++设计模式(李建忠),参考教材为《设计模式:可复用面向对象软件的基础》。本栏目 [A] 系列文章中的图件和笔记,部份来自上述资源。

从封装变化角度对模式分类!:

  • 组件协作
  • 单一职责
  • 对象创建
  • 对象性能
  • 接口隔离
  • 状态变化
    在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一问题提出了解决方案。
    典型模式
    • 状态模式 State
    • 备忘录模式 Memento
  • 数据结构
  • 行为变化
  • 领域问题
状态模式 State

在这里插入图片描述

  • 定义:允许一个对象在其内部状态改变时改变它的行为,从而使对象看起来似乎修改了其行为。
  • 应用举例:做一个网络的应用,根据网络的状态(open,close,connect)来做不同的操作,且做完之后就切换状态。
  • 一般不考虑设计原则不使用设计模式的 代码可以这么写:
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(){
        //***
    }
};
  • 分析:以上代码,用枚举变量来表示网络状态的类型,NetworkProcessor 中变量 state 表示当前网络状态,operation1,2,3 是三个根据不同网络状态做出不同行为然后切换网络状态state的成员函数,函数中用 if else 做状态判断。这样的设计在 策略模式 中就谈过,一旦有新增的网络状态,修改就很 麻烦。不符合对修改封闭,对扩展开放的原则。
  • 在类的方法中出现 多个 if else 就值得注意了,这可能需要更好的设计。如下
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();
    }
};

class CloseState:public NetworkState{ }
//...类似上面的OpenState

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;
        //...
    }
};
  • 分析:首先提出网络状态抽象基类,基类中有 operation1,2,3 这三个根据不同网络状态做出不同行为然后切换网络状态state的成员函数,成员变量 pNext 记录切换后的状态。打开,关闭,连接这三个网络状态继承上述基类,且这个类在系统中只需存在一个对象即可,所以用单件模式。operation函数在执行对应操作后,给 pNext 赋值新的网络状态。
  • NetworkProcessor 将网络状态类作为成员类 pState,使用其功能,三个operation函数中调用pState的三个对应函数,然后将 pState 赋值新的网络状态对象。这样设计,做到了网络状态发生变化时相应的改变行为。
  • 这样设计,以后改变 一般只需要增加新的子类即可。无需改变已有的代码。
    在这里插入图片描述
    在这里插入图片描述
备忘录模式 Memento

在这里插入图片描述

  • 定义:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。
class Memento
{
    string state;
    //..
public:
    Memento(const string & s) : state(s) {}
    string getState() const { return state; }
    void setState(const string & s) { state = s; }
};

class Originator
{
    string state;
    //....
public:
    Originator() {}
    Memento createMomento() {
        Memento m(state);
        return m;
    }
    void setMomento(const Memento & m) {
        state = m.getState();
    }
};

int main() {
    Originator orginator;
    //捕获对象状态,存储到备忘录
    Memento mem = orginator.createMomento();
    //... 改变orginator状态
    //从备忘录中恢复
    orginator.setMomento(memento);
}
  • 使用 Memento 来存储 Originator 的状态,之后在必要的时间点,再把以前存储的状态提供给 Originator,让其恢复到特定历史时间点的状态。
    在这里插入图片描述
    在这里插入图片描述
  • 此模式现在而言有些过时了。
Stkcd [股票代码] ShortName [股票简称] Accper [统计截止日期] Typrep [报表类型编码] Indcd [行业代码] Indnme [行业名称] Source [公告来源] F060101B [净利润现金净含量] F060101C [净利润现金净含量TTM] F060201B [营业收入现金含量] F060201C [营业收入现金含量TTM] F060301B [营业收入现金净含量] F060301C [营业收入现金净含量TTM] F060401B [营业利润现金净含量] F060401C [营业利润现金净含量TTM] F060901B [筹资活动债权人现金净流量] F060901C [筹资活动债权人现金净流量TTM] F061001B [筹资活动股东现金净流量] F061001C [筹资活动股东现金净流量TTM] F061201B [折旧摊销] F061201C [折旧摊销TTM] F061301B [公司现金流1] F061302B [公司现金流2] F061301C [公司现金流TTM1] F061302C [公司现金流TTM2] F061401B [股权现金流1] F061402B [股权现金流2] F061401C [股权现金流TTM1] F061402C [股权现金流TTM2] F061501B [公司自由现金流(原有)] F061601B [股权自由现金流(原有)] F061701B [全部现金回收率] F061801B [营运指数] F061901B [资本支出与折旧摊销比] F062001B [现金适合比率] F062101B [现金再投资比率] F062201B [现金满足投资比率] F062301B [股权自由现金流] F062401B [企业自由现金流] Indcd1 [行业代码1] Indnme1 [行业名称1] 季度数据,所有沪深北上市公司的 分别包含excel、dta数据文件格式及其说明,便于不同软件工具对数据的分析应用 数据来源:基于上市公司年报及公告数据整理,或相关证券交易所、各部委、省、市数据 数据范围:基于沪深北证上市公司 A股(主板、中小企业板、创业板、科创板等)数据整理计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值