【设计模式之状态模式 -- 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.
相关推荐
C++ 老炮儿的技术栈6 小时前
volatile使用场景
linux·服务器·c语言·开发语言·c++
hz_zhangrl6 小时前
CCF-GESP 等级考试 2026年3月认证C++一级真题解析
开发语言·c++·gesp·gesp2026年3月·gespc++一级
Liu628886 小时前
C++中的工厂模式高级应用
开发语言·c++·算法
波特率1152007 小时前
const关键字与函数的重载
开发语言·c++·函数重载
干啥啥不行,秃头第一名7 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
2301_807367198 小时前
C++中的解释器模式变体
开发语言·c++·算法
前端不太难9 小时前
ArkUI 的页面生命周期详解
状态模式
2301_8194143010 小时前
C++与区块链智能合约
开发语言·c++·算法
不想看见40410 小时前
Valid Parentheses栈和队列--力扣101算法题解笔记
开发语言·数据结构·c++
老约家的可汗10 小时前
C/C++内存管理探秘:从内存分布到new/delete的底层原理
c语言·c++