(十一)Head first design patterns状态模式(c++)

这篇具有很好参考价值的文章主要介绍了(十一)Head first design patterns状态模式(c++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

状态模式

如何去描述状态机?

假设你需要实例化一台电梯,并模仿出电梯的四个状态:开启、关闭、运行、停止。也许你会这么写

class ILift{
public:
    virtual void open(){}
    virtual void close(){}
    virtual void run(){}
    virtual void stop(){}
};
class Lift : public ILift{
public:
    void open(){ std::cout << "电梯门关闭..." << std::endl; }
    void close(){ std::cout << "电梯门开启..." << std::endl; }
    void run(){ std::cout << "电梯上下跑起来..." << std::endl; }
    void stop(){ std::cout << "电梯停止了..." << std::endl; }
};
int main(){
    ILift* lift = new Lift();
    lift->open();
    lift->close();
    lift->run();
    lift->stop();
}

这样写未免太草率了。因为电梯在门开启的时候一般是不能运行的,在运行的时候一般也不会门开启,而在停止工作状态一般不会再去执行关门这个动作。所以需要设置一些状态去限制这台电梯的行为。于是在类Lift中存储电梯目前的状态,在执行每个动作的时候用swith分支来判断当前动作是否有效,以及更新当前状态。于是有了下面的代码

(十一)Head first design patterns状态模式(c++),设计模式cpp,设计模式,状态模式,c++

class ILift{
public:
    virtual void setState(int state){};
    virtual void open(){}
    virtual void close(){}
    virtual void run(){}
    virtual void stop(){}
};
class Lift : public ILift{
public:
    Lift(int state):state(state){}
    void setState(int state){ this->state = state; }
    void close(){
        switch(state){
            case OPENING_STATE:
                closeWithoutLogic();
                setState(CLOSING_STATE);
                break;
            case CLOSING_STATE:
                break;
            case RUNNING_STATE:
                break;
            case STOPPING_STATE:
                break;
        }
    }
    void open(){
        switch(state){
            case OPENING_STATE:
                break;
            case CLOSING_STATE:
                openWithoutLogic();
                setState(OPENING_STATE);
                break;
            case RUNNING_STATE:
                break;
            case STOPPING_STATE:
                openWithoutLogic();
                setState(OPENING_STATE);
        }
    }
    void run(){
        switch(state){
            case OPENING_STATE:
                break;
            case CLOSING_STATE:
                runWithoutLogic();
                setState(RUNNING_STATE);
                break;
            case RUNNING_STATE:
                break;
            case STOPPING_STATE:
                runWithoutLogic();
                setState(RUNNING_STATE);
        }
    }
    void stop(){
        switch(state){
            case OPENING_STATE:
                break;
            case CLOSING_STATE:
                stopWithoutLogic();
                setState(STOPPING_STATE);
                break;
            case RUNNING_STATE:
                stopWithoutLogic();
                setState(STOPPING_STATE);
                break;
            case STOPPING_STATE:
                break;
        }
    }
    void closeWithoutLogic(){ std::cout << "电梯门关闭..." << std::endl; }
    void openWithoutLogic() { std::cout << "电梯门开启..." << std::endl; }
    void runWithoutLogic()  { std::cout << "电梯上下跑起来..." << std::endl; }
    void stopWithoutLogic() { std::cout << "电梯停止了..." << std::endl; }
private:
    int state;
};
int main(){
    ILift* lift = new Lift(STATE(OPENING_STATE));
    lift->close(); // 关闭
    lift->open();  // 开启
    lift->run();   // 无动作
    lift->stop();  // 无动作
    lift->close(); // 关闭
}

这个类的实现代码特别长,内部包含了太多的switch语句。而且当需要增加状态时,比如说电梯停电状态和电梯维修状态,就需要去更改里面的switch语句。这样写违背了开闭原则以及单一性原则。为了在增加状态的时候尽量少的修改原有代码,可以将swtich中的每个状态抽离出来单独包装成类。

(十一)Head first design patterns状态模式(c++),设计模式cpp,设计模式,状态模式,c++

创建context类,在context类中存有LiftState对象用来记录当前的状态。此时context目前拥有四种状态对象,用指针维护。每种状态的逻辑由各自类在内部实现。当电梯发生动作,即context调用函数时,函数内部会调用当前state对应的方法,于是这部分逻辑转交由state内部实现。具体代码如下:

#include<iostream>
#include<string>

using namespace std;

class ContextBase;
class LiftState{
public:
    void setContext(ContextBase* context){ this->mContext = context; }
    virtual void open(){}
    virtual void close(){}
    virtual void run(){}
    virtual void stop(){}
    ContextBase* getContext(){ return mContext; }
public:
    ContextBase* mContext;
};
class ContextBase{
public:
    ContextBase(){}
    virtual LiftState* getLiftState(){}
    virtual LiftState* getOpenningState(){}
    virtual LiftState* getClosingState(){}
    virtual LiftState* getRunningState(){}
    virtual LiftState* getStoppingState(){}
    virtual void setLiftState(LiftState* liftState){}
    virtual void open(){}
    virtual void close(){}
    virtual void run(){}
    virtual void stop(){}
public:
    LiftState* liftState;
};
class OpenningState : public LiftState{
    void open(){
        std::cout << "lift open..." << std::endl;
    }
    void close(){
        mContext->setLiftState(mContext->getClosingState());
        mContext->getLiftState()->close();
    }
    void run(){}
    void stop(){}
};
class ClosingState : public LiftState{
    void open(){
        mContext->setLiftState(mContext->getOpenningState());
        mContext->getLiftState()->open();
    }
    void close(){
        std::cout << "lift close..." << std::endl;
    }
    void run(){
        mContext->setLiftState(mContext->getRunningState());
        mContext->getLiftState()->run();
    }
    void stop(){
        mContext->setLiftState(mContext->getStoppingState());
        mContext->getLiftState()->stop();
    }
};
class RunningState : public LiftState{
    void open(){
    }
    void close(){
    }
    void run(){
        std::cout << "lift running..." << std::endl;
    }
    void stop(){
        mContext->setLiftState(mContext->getStoppingState());
        mContext->getLiftState()->stop();
    }
};
class StoppingState : public LiftState{
    void open(){
        mContext->setLiftState(mContext->getOpenningState());
        mContext->getLiftState()->open();
    }
    void close(){
    }
    void run(){
        mContext->setLiftState(mContext->getRunningState());
        mContext->getLiftState()->run();
    }
    void stop(){
        std::cout << "lift stopping..." << std::endl;
    }
};

class Context : public ContextBase{
public:
    Context(){}
    LiftState* getLiftState(){
        return liftState;
    }
    LiftState* getOpenningState(){
        return openningState;
    }
    LiftState* getClosingState(){
        return closingState;
    }
    LiftState* getRunningState(){
        return runningState;
    }
    LiftState* getStoppingState(){
        return stoppingState;
    }
    void setLiftState(LiftState* liftState){
        this->liftState = liftState;
        this->liftState->setContext(this);
    }
    void open(){ liftState->open(); }
    void close(){ liftState->close(); }
    void run(){ liftState->run(); }
    void stop(){ liftState->stop(); }
public:
    LiftState* openningState = new OpenningState();
    LiftState* closingState  = new ClosingState();
    LiftState* runningState  = new RunningState();
    LiftState* stoppingState = new StoppingState();
};

int main(){
    Context* context = new Context;
    context->setLiftState(new ClosingState());
    context->open();
    context->close();
    context->run();
    context->stop();
}

状态模式的优势:

当由新的状态加入时,只需要扩展子类,而不需要过多地更改原有代码。遵守了开闭原则。

当动作和状态更新等逻辑交由状态类内部实现,实现了单一性设计原则。

参考

Java设计模式——状态模式(STATE PATTERN)_java中state pattern-CSDN博客​​​​​​​文章来源地址https://www.toymoban.com/news/detail-817443.html

到了这里,关于(十一)Head first design patterns状态模式(c++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【设计模式】Head First 设计模式——策略模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 将行为想象为一族算法,定义算法族,分别封装起来,让他们之间可以互相替换,使得算

    2024年02月11日
    浏览(41)
  • 【设计模式】Head First 设计模式——抽象工厂模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 提供一个接口,让该接口负责创建一系列“相关或者相互依赖的对象”,无需指定他们具

    2024年02月10日
    浏览(43)
  • 【设计模式】Head First 设计模式——构建器模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 ​ 将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同

    2024年02月09日
    浏览(40)
  • 【设计模式】Head First 设计模式——装饰者模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 动态地将责任附加到对象上,若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

    2024年02月10日
    浏览(44)
  • 【设计模式】Head First 设计模式——工厂方法模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使得一个类的实

    2024年02月10日
    浏览(50)
  • 【设计模式】Head First 设计模式——观察者模式 C++实现

    设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 主题对象(出版者)管理某些数据,当主题内的数据改变,就会通知观察者(订阅者)。

    2024年02月10日
    浏览(42)
  • 设计模式二十一:状态模式(State Pattern)

    一个对象的内部状态发生变化时,允许对象改变其行为。这种模式使得一个对象看起来好像在运行时改变了它的类,主要目的是将状态的行为从主要对象中分离出来,使得主要对象不必包含所有状态的逻辑,而是将每个状态的行为封装在独立的类中。这有助于减少代码的重复

    2024年02月11日
    浏览(48)
  • 【Head First 设计模式】-- 观察者模式

    客户有一个WeatherData对象,负责追踪温度、湿度和气压等数据。现在客户给我们提了个需求,让我们利用WeatherData对象取得数据,并更新三个布告板:目前状况、气象统计和天气预报。 WeatherData对象提供了4个接口: getTemperature():获取温度 getHumidity():获取湿度 getPressure():获

    2024年02月05日
    浏览(46)
  • 【设计模式】Bridge Design pattern 桥接模式

    多个维度的变化引起的继承组合指数级增长 例子 一个物体有不同形状和不同颜色,如何用类来表示它们,这里包含了两个变化维度,一个是物体的形状,一个是颜色 继承的方式 如果使用继承的方式,此时要增加一个形状就要多两个类,或者增加一个颜色也要多两个类,这个

    2023年04月08日
    浏览(43)
  • 设计模式十一:外观模式(Facade Pattern)

    外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,用于访问系统中的一组复杂子系统。外观模式通过将复杂子系统的接口封装在一个高层接口中,简化了客户端与子系统之间的交互,使得客户端代码更加清晰、简洁。 外观模式的使用场景包括: 简化

    2024年02月13日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包