十分钟学会一个设计模式---行为模式---状态模式

221 阅读1分钟

一、简述

  1. 与策略模式相似,后续总结区别
  2. 根据对象所处不同的状态,执行不同的逻辑,有效的减少对象中if和else的逻辑

二、未使用模式

// 用糖果机 投币退币举例
// 两种状态
enum State {
    NO_QUARTER,  // 没有硬币
    HAS_QUARTER  // 有硬币
};

// 两种行为,根据状态不同,执行不同逻辑
// 扩展性比较差,新增状态需要修改两种行为的代码逻辑
class GumballMachine {
private:
    State *state;

//    投币行为
    void Insert() {
        if (*state == NO_QUARTER) { //随着状态增多,if,else会变多
            cout << "投币成功";
            *state = HAS_QUARTER;
        } else if (*state == HAS_QUARTER) {
            cout << "投币失败";
        }
    }

//    退币行为
    void Back() {
        if (*state == NO_QUARTER) {
            cout << "退币失败";
        } else if (*state == HAS_QUARTER) {
            cout << "退币成功";
            *state = NO_QUARTER;
        }
    }
};

三、使用模式

// 使用状态设计模式,将行为委托给状态
class StatePattern {
public:
    virtual void Insert() = 0;

    virtual void Back() = 0;
};

class NoQuarterState : public StatePattern {
private:
    GumballMachinePattern *gumballMachinePattern;
public:
    void Insert() override {
        cout << "投币成功";
        gumballMachinePattern->SetState(gumballMachinePattern->hasQuarterState);
    }

    void Back() override {
        cout << "投币失败";
    }
};

class HasQuarterState : public StatePattern {
private:
    GumballMachinePattern *gumballMachinePattern;
public:
    void Insert() override {
        cout << "投币失败";
    }

    void Back() override {
        cout << "投币成功";
        gumballMachinePattern->SetState(gumballMachinePattern->noQuarterState);
    }
};

// 糖果机
class GumballMachinePattern : public StatePattern {
private:
    NoQuarterState *noQuarterState;
    HasQuarterState *hasQuarterState;

    StatePattern *state;
public:
    GumballMachinePattern(NoQuarterState *noQuarterState, HasQuarterState *hasQuarterState) :
            noQuarterState(noQuarterState),
            hasQuarterState(hasQuarterState),
            state(noQuarterState) {}
//  行为交给具体的状态类
    void Insert() override {
        state->Insert();
    }

    void Back() override {
        state->Back();
    }

    void SetState(StatePattern *statePattern) {
        state = statePattern;
    }
};

这种设计下,糖果机根本不需要清楚状态的改变,它只用调用状态的方法就行。状态的改变是在状态内部发生的。此时增加一个状态,不需要修改糖果机方法,再增加类就可以