19 状态(State)模式

状态模式

1.1 分类

(对象)行为型

1.2 提出问题

开发一个糖果贩卖机,当投入硬币按下按钮,糖果机将掉落一枚糖果。当没有投入硬币,直接按下按钮,将会得到请投币的提示。

1.3 解决方案

允许一个对象在其内部状态改变时改变它的行为。对象看起来适合改变了它的类。

1.4 实现类图

在这里插入图片描述

  1. 上下文(Context)保存了对于一个具体状态对象的引用,并会将所有与该状态相关的工作委派给它。
  2. 状态(State)接口会声明特定于状态的方法。
  3. 具体状态(Concrete States)会自行实现特定于状态的方法。
  4. 上下文和具体状态都可以设置上下文的下个状态,并可通过替换连接到上下文的状态对象来完成实际的状态转换。

1.5 示例代码

#include <iostream>

//class CandyMachine;
class State {
protected:
   // CandyMachine* m_candyMachine;
public:
    //void setContext(CandyMachine* candyMachine) {
    //    m_candyMachine = candyMachine;
    //}
    //virtual ~State(){}
    
    virtual void getCandy() = 0;
    virtual void returnCoin() = 0;
    virtual void putCoin() = 0;
};

class NoCoinState :public State {
    virtual void getCandy() override {
        std::cout << "请先投币。\n";
    }
    virtual void returnCoin() override {
        std::cout << "你并没有投币。\n";
    }
    virtual void putCoin()override {
        std::cout << "投币成功。\n";
    }
};
class HaveCoinState :public State {
    virtual void getCandy() override {
        std::cout << "糖果投放中......\n";
    }
    virtual void returnCoin() override {
        std::cout << "硬币退回中......\n";
    }
    virtual void putCoin() override {
        std::cout << "重复投币。\n";
    }
};

//Context
class CandyMachine {
private:
    State* m_currentState;
    State* m_haveCoinState;
    State* m_noCoinState;
public:
    CandyMachine() {
        m_haveCoinState = new HaveCoinState();
        m_noCoinState = new NoCoinState();
        m_currentState = m_noCoinState;
        std::cout << "糖果机:当前状态为--->" << typeid(*m_currentState).name() << "。\n";
    }
    ~CandyMachine() {
        delete m_haveCoinState;
        delete m_noCoinState;
    }
    void putCoin() {
        std::cout << "糖果机:putCoin。\n";
        m_currentState->putCoin();
        transitionTo(m_haveCoinState);
    }
    void getCandy() {
        std::cout << "糖果机:getCandy。\n";
        m_currentState->getCandy();
        transitionTo(m_noCoinState);
    }
    void returnCoin() {
        std::cout << "糖果机:returnCoin。\n";
        m_currentState->returnCoin();
        transitionTo(m_noCoinState);
    }
private:
    void transitionTo(State* state) {
        m_currentState = state;
        std::cout << "糖果机:当前状态为--->" << typeid(*m_currentState).name() << "。\n";
    }
};
int main()
{
    CandyMachine* candyMachine = new CandyMachine;
    candyMachine->getCandy();
    candyMachine->returnCoin();
    candyMachine->putCoin();
    candyMachine->getCandy();
    candyMachine->returnCoin();
    delete candyMachine;
}

1.6 举个栗子

状态模式将根据当前回放状态,让媒体播放器中的相同控件完成不同的行为。
在这里插入图片描述

1.7 总结

1.7.1 优点

  1. 单一职责原则。将与特定状态相关的代码放在单独的类中。
  2. 开闭原则。无需修改已有状态类和上下文就能引入新状态。
  3. 通过消除臃肿的状态机条件语句简化上下文代码。

1.7.2 缺点

如果状态机只有很少的几个状态,或者很少发生改变,那么应用该模式可能会显得小题大作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值