设计模式--状态模式

1.定义(目的)

实现状态和行为的分离。

2.使用场景

行为随着状态改变(key),行为实现中有较多if else或switch语句

3.类图

 

 a.上图do1,do2,do3就是行为,state1,state2,state3就是行为。可以看到行为和状态分离了,增加状态满足开闭原则,但是增加行为不满足。

b. 状态模式和策略模式的类图类似,策略模式各个策略间是平等的没有联系的;而状态模式的各个状态是有关联的,比如state1的do1要调用state2的do1来实现,那么就需要在state中也维护一个context,如下:

   void do()
    {

        context->setState(Context::State1);
        context->getState().do();
    }
 


c.策略模式和状态模式的应用场景不同:策略模式是一个行为,有多种策略可以实现;状态模式是一个行为,在不同状态下得表现的不一样。


4. 优缺点

(2)优点

  ①简化逻辑。单独的类来封装一个状态的处理,代码结构化和意图更清晰。对于依赖状态的if-else的情况,每个if或else可以由一个状态来代表。

  ②分离状态和行为。客户端通过context公共接口修改状态,只需关心状态的切换,不用关心状态对应的处理。增加状态满足开闭原则,修改一个状态行为,不会影响其他状态的行为,符合职责单一原则。

  ③增强扩展性。行为的公共接口,使得拓展状态,只需增加一个状态类即可。

(2)缺

          子类膨胀,程序引入过多状态类。

增加行为,不符合开闭原则

代码转至https://www.cnblogs.com/5iedu/p/5637909.html

#include <iostream>
#include <string>

using namespace std;

class Context; //前向声明

//********************(State接口)********************************
//抽象电梯状态
class LiftState
{
protected:
    Context* context;
public:
    void setContext(Context* context)
    {
        this->context = context;
    }

    //电梯开启动作
    virtual void open() = 0;
    //电梯关门动作
    virtual void close() = 0;
    //电梯运行动作
    virtual void run() = 0;
    //电梯停止动作
    virtual void stop() = 0;
};

//***********************Context环境类*****************************
class Context
{
private:
    LiftState* liftState;
public:
    static LiftState* openningState;
    static LiftState* closingState;
    static LiftState* runningState;
    static LiftState* stoppingState;

    LiftState& getLiftState()
    {
        return *liftState;
    }

    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();
    }
};

//***************************ConcreteState类********************************
//开门状态
class OpenningState : public LiftState
{
public:
    //打开电梯门
    void open()
    {
        cout << "电梯门开启..." << endl;
    }

    //开门状态下,可以按下“关门”按钮
    void close()
    {
        //将当前状态修改为关门状态
        context->setLiftState(Context::closingState);
        //关门
        context->getLiftState().close();
    }

    //开门状态下不能运行!
    void run()
    {
        //do nothing;
    }

    //开门状态下,按停止没效果
    void stop()
    {
        //do nothing
    }
};

//关门状态
class ClosingState : public LiftState
{
public:
    //打开电梯门
    void open()
    {
        //将当前状态修改为开门状态
        context->setLiftState(Context::openningState);
        context->getLiftState().open();
    }

    //关门状态
    void close()
    {
        cout << "电梯门关闭..." << endl;
    }

    //关门状态,可以按“运行”按钮
    void run()
    {
        //将当前状态修改为运行状态
        context->setLiftState(Context::runningState);
        context->getLiftState().run();
    }

    //关门状态下,可以切换到停止状态
    void stop()
    {
        //将当前状态修改为停止状态
        context->setLiftState(Context::stoppingState);
        context->getLiftState().stop();
    }
};

//运行状态
class RunningState : public LiftState
{
public:
    //运行状态,按“开门”按钮没效课
    void open()
    {
        //do nothing
    }

    //运行状态按“关门”按钮没效果
    void close()
    {
        //do nothing;
    }

    //运行状态
    void run()
    {
        cout << "电梯上下运行..." << endl;
    }

    //运行状态下,可按“停止”
    void stop()
    {
        //将当前状态修改为停止状态
        context->setLiftState(Context::stoppingState);
        context->getLiftState().stop();
    }
};

//停止状态
class StoppingState : public LiftState
{
public:
    //停止状态,可以打开电梯门
    void open()
    {
        //将当前状态修改为开门状态
        context->setLiftState(Context::openningState);
        context->getLiftState().open();
    }

    //停止状态下,可以按下“关门”按钮没效果
    void close()
    {
        //do nothing
    }

    //关门状态,可以按“运行”按钮!
    void run()
    {
        //将当前状态修改为运行状态
        context->setLiftState(Context::runningState);
        context->getLiftState().run();
    }

    //开门状态下,按停止没效果
    void stop()
    {
        cout << "电梯停止了..." << endl;
    }
};

LiftState* Context::openningState = new OpenningState();
LiftState* Context::closingState  = new ClosingState();
LiftState* Context::runningState  = new RunningState();
LiftState* Context::stoppingState = new StoppingState();

int main()
{
    Context context;
    context.setLiftState(Context::closingState);

    context.open();
    context.close();
    context.run();
    context.stop();

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值