【设计模式之状态模式 -- C++】

状态模式 -- 状态切换,行为变化

状态模式(State Pattern)允许一个对象在其内部状态改变时改变它的行为。这种模式下,对象看起来似乎修改了它的类。状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。将状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。

组成
  1. 定义状态接口(State):这个接口将封装与上下文的一个特定状态相关的行为。

  2. 创建具体状态类(Concrete States):这些类实现了状态接口,每个类对应一种状态,并实现在该状态下应有的行为。

  3. 定义上下文(Context):这个类包含一个指向状态对象的引用,这个引用可以用来改变其行为。

实现伪代码:

cpp 复制代码
// State 接口声明了特定状态下的行为
interface State {
    method1();
    method2();
}

// ConcreteStateA 和 ConcreteStateB 实现了 State 接口
class ConcreteStateA : State {
    method1() { // 实现细节 }
    method2() { // 实现细节 }
}

class ConcreteStateB : State {
    method1() { // 实现细节 }
    method2() { // 实现细节 }
}

// Context 类包含一个 State 类型的对象,并允许设置当前状态
class Context {
    private State state;

    setState(State state) {
        this.state = state;
    }

    method1() {
        state.method1();
    }

    method2() {
        state.method2();
    }
}
优点
  1. 封装性:状态模式通过将每个状态封装到一个类中,将与状态相关的行为局部化,并且将不同状态的行为分割开来,增强了系统的封装性。
  2. 去除庞大的条件分支语句:状态模式避免了在操作中使用大量的条件分支语句,使得状态的转换更加明确,且易于管理和维护。
  3. 扩展性:由于状态是由类表示的,所以可以很容易地添加新的状态,符合开闭原则。
  4. 职责清晰:每个状态类只关注于一种状态的行为实现,使得职责分配明确。
使用场景
  1. 对象的行为依赖于其状态:当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时,可以使用状态模式。
  2. 复杂的条件分支需要简化:当一个操作中包含庞大的多分支结构,并且这些分支依赖于对象的状态时,状态模式可以将每一分支转换为一个状态类的一个实现。
  3. 跨类的状态转换:当状态的转换逻辑分散在多个类中时,使用状态模式可以将这些逻辑集中管理,使得状态转换更加清晰和集中。
  4. 状态模式也常用于实现有限状态机:在需要通过一系列输入导致不同状态之间转换和操作的场景中,状态模式提供了一种清晰的方式来实现这种机制。

总的来说,状态模式适用于对象状态多变且相互依赖,需要在运行时根据状态改变对象行为的场景。通过使用状态模式,可以使得状态转换逻辑更加清晰,易于扩展和维护。

实现
  1. state接口
cpp 复制代码
class State {
public:
    virtual void handleRequest() = 0;
    virtual ~State() = default;
};
  1. 具体状态实现a,b
cpp 复制代码
class ConcreteStateA : public State {
public:
    void handleRequest() override {
        std::cout << "ConcreteStateA handles request." << std::endl;
    }
};
class ConcreteStateB : public State {
public:
    void handleRequest() override {
        std::cout << "ConcreteStateB handles request." << std::endl;
    }
};
  1. 上下文
cpp 复制代码
class Context {
private:
    std::unique_ptr<State> state;
public:
    Context(std::unique_ptr<State> state) : state(std::move(state)) {}
    void setState(std::unique_ptr<State> newState) {
        state = std::move(newState);
    }
    void request() {
        state->handleRequest();
    }
};
  1. 测试
cpp 复制代码
int main() {
    Context context(std::make_unique<ConcreteStateA>());
    context.request(); // 输出: ConcreteStateA handles request.

    context.setState(std::make_unique<ConcreteStateB>());
    context.request(); // 输出: ConcreteStateB handles request.

    return 0;
}
  1. 结果
shell 复制代码
ConcreteStateA handles request.
ConcreteStateB handles request.
相关推荐
佛祖让我来巡山7 小时前
设计模式深度解析:策略模式、责任链模式与模板模式
设计模式·责任链模式·策略模式·模版模式
__万波__8 小时前
二十三种设计模式(三)--抽象工厂模式
java·设计模式·抽象工厂模式
转转技术团队8 小时前
VDOM 编年史
前端·设计模式·前端框架
招摇的一半月亮9 小时前
P2242 公路维修问题
数据结构·c++·算法
f***019310 小时前
CC++链接数据库(MySQL)超级详细指南
c语言·数据库·c++
合方圆~小文10 小时前
球型摄像机作为现代监控系统的核心设备
java·数据库·c++·人工智能
明洞日记11 小时前
【设计模式手册014】解释器模式 - 语言解释的优雅实现
java·设计模式·解释器模式
ZHE|张恒11 小时前
设计模式(十六)迭代器模式 — 统一访问集合元素的方式,不暴露内部结构
设计模式·迭代器模式
椰萝Yerosius11 小时前
[题解]2024CCPC郑州站——Z-order Curve
c++·算法
todoitbo13 小时前
基于 DevUI MateChat 搭建前端编程学习智能助手:从痛点到解决方案
前端·学习·ai·状态模式·devui·matechat