行为型模式-状态模式

发布时间 2023-11-14 21:42:34作者: Qt小罗

1 什么是状态模式

状态模式(State Pattern)是一种行为型设计模式,它允许对象在其内部状态改变时改变它的行为。状态模式通过将对象的状态封装成独立的类,使得对象在不同状态下可以有不同的行为,同时使状态转换更加简洁和可控。

在状态模式中,包括以下几个核心角色:

  • Context(上下文):定义客户感兴趣的接口,维护一个当前状态对象,并将与状态相关的请求委托给当前状态对象处理。
  • State(状态):定义一个接口,封装与Context的一个特定状态相关的行为。
  • ConcreteState(具体状态):每一个具体状态类实现State接口,负责该状态下的具体行为。

2 举个例子

下面以一个自动售货机的例子来说明状态模式。

#include <iostream>

// 售货机状态接口
class VendingMachineState {
public:
    virtual void insertCoin() = 0;
    virtual void pressButton() = 0;
    virtual void dispenseItem() = 0;
    virtual void returnCoin() = 0;
};

// 具体状态类:无硬币
class NoCoinState : public VendingMachineState {
public:
    void insertCoin() override {
        std::cout << "Coin inserted" << std::endl;
    }

    void pressButton() override {
        std::cout << "Please insert a coin" << std::endl;
    }

    void dispenseItem() override {
        std::cout << "Please insert a coin" << std::endl;
    }

    void returnCoin() override {
        std::cout << "No coin to return" << std::endl;
    }
};

// 具体状态类:有硬币
class HasCoinState : public VendingMachineState {
public:
    void insertCoin() override {
        std::cout << "Coin already inserted" << std::endl;
    }

    void pressButton() override {
        std::cout << "Item dispensed" << std::endl;
    }

    void dispenseItem() override {
        std::cout << "Please press the button" << std::endl;
    }

    void returnCoin() override {
        std::cout << "Coin returned" << std::endl;
    }
};

// 上下文类:自动售货机
class VendingMachine {
private:
    VendingMachineState* state;

public:
    VendingMachine() {
        state = new NoCoinState();
    }

    void setState(VendingMachineState* newState) {
        delete state;  // 释放原来的状态对象
        state = newState;
    }

    void insertCoin() {
        state->insertCoin();
    }

    void pressButton() {
        state->pressButton();
    }

    void dispenseItem() {
        state->dispenseItem();
    }

    void returnCoin() {
        state->returnCoin();
    }

    ~VendingMachine() {
        delete state;  // 释放状态对象
    }
};

int main() {
    VendingMachine vendingMachine;

    vendingMachine.insertCoin();  // 输出: Coin inserted
    vendingMachine.pressButton();  // 输出: Please insert a coin

    vendingMachine.setState(new HasCoinState());  // 切换状态

    vendingMachine.pressButton();  // 输出: Item dispensed
    vendingMachine.returnCoin();   // 输出: Coin returned

    return 0;
}

在这个示例中,VendingMachine 是上下文类,负责维护当前状态对象,并委托与状态相关的请求给当前状态对象处理。VendingMachineState 是状态接口,定义了各种状态的操作。NoCoinState 和 HasCoinState 是具体状态类,分别代表售货机中没有硬币和有硬币两种状态下的操作。

在 main 函数中,我们创建了售货机对象,并测试了售货机的各种状态下的行为。最后,我们切换了售货机的状态,以展示状态模式的灵活性和可扩展性。

3 总结

通过状态模式,我们可以将与特定状态相关的行为封装到独立的状态类中,使得状态之间的切换变得更加灵活和可维护,同时使上下文类的代码变得简洁清晰。