设计模式——状态模式

状态模式

状态模式是一种行为设计模式,让你能在一个对象的内部状态变化时改变其行为,使其看上去就像是改变了自身所属的类一样

其主要思想是程序在任意时刻仅可处于几种有限的状态中。 在任何一个特定状态中, 程序的行为都不相同, 且可瞬间从一个状态切换到另一个状态。 不过, 根据当前状态, 程序可能会切换到另外一种状态, 也可能会保持当前状态不变。 这些数量有限且预先定义的状态切换规则被称为转移。

为了能根据当前状态选择完成相应行为的方法, 绝大部分方法中会包含复杂的条件语句。 修改其转换逻辑可能会涉及到修改所有方法中的状态条件语句, 导致代码的维护工作非常艰难。

状态模式建议为对象的所有可能状态新建一个类, 然后将所有状态的对应行为抽取到这些类中。

状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以简化复杂的判断逻辑。

c++ 复制代码
#include <iostream>
#include <string>

using namespace std;

class Context;

// 基状态提供了所有具体的状态的接口
class State{
protected:
    Context *context_;

public:
    virtual ~State(){}

    void set_context(Context *context){
        this->context_ = context;
    }

    virtual void Handle1() = 0;
    virtual void Handle2() = 0;
};

// Context 定义了客户端感兴趣的接口。
// 它还维护对 State 子类实例的引用,该子类实例表示 Context 的当前状态。
class Context{
private:
    State *state_;

public:
    Context(State *state):state_(nullptr){
        this->TransitionTo(state);
    }

    ~Context(){
        delete state_;
    }

    // 允许在运行时更改State对象
    void TransitionTo(State *state){
        cout << "Context: Transition to " << typeid(*state).name() << endl;
        if(this->state_ != nullptr)
            delete this->state_;
        this->state_ = state;
        this->state_->set_context(this);
    }

    // Context将其部分行为委托给当前的State对象
    void Request1(){
        this->state_->Handle1();
    }
    void Request2(){
        this->state_->Handle2();
    }
};

// 具体状态实现与上下文状态相关的各种行为
class ConcreteStateA : public State{
public:
    void Handle1() override;

    void Handle2() override{
        cout << "ConcreteStateA handles request2." << endl;
    }
};

class ConcreteStateB : public State{
public:
    void Handle1() override{
        std::cout << "ConcreteStateB handles request1.\n";
    }

    void Handle2() override{
        std::cout << "ConcreteStateB handles request2.\n";
        std::cout << "ConcreteStateB wants to change the state of the context.\n";

        this->context_->TransitionTo(new ConcreteStateA);
    }
};

// 写在这里是因为里面new了ConcreteStateB
void ConcreteStateA::Handle1(){
    {
        std::cout << "ConcreteStateA handles request1.\n";
        std::cout << "ConcreteStateA wants to change the state of the context.\n";

        this->context_->TransitionTo(new ConcreteStateB);
    }
}

void ClientCode() {
    Context *context = new Context(new ConcreteStateA);
    context->Request1();
    context->Request2();
    delete context;
}

int main() {
    ClientCode();
    return 0;
}

运行结果

复制代码
Context: Transition to 14ConcreteStateA
ConcreteStateA handles request1.
ConcreteStateA wants to change the state of the context.
Context: Transition to 14ConcreteStateB
ConcreteStateB handles request2.
ConcreteStateB wants to change the state of the context.
Context: Transition to 14ConcreteStateA
相关推荐
南一Nanyi4 小时前
依赖注入和控制反转
前端·设计模式·nestjs
JaneConan6 小时前
鸿蒙 ArkUI 深水区:@Watch 和 @Observed,状态变了「自动跑」+ 嵌套对象「深层重绘」
开发语言·后端·ui·harmonyos
施棠海9 小时前
设计稿一键变成可运行的Android页面:Pixel2XML全流程UI开发框架实战(附完整源码)
android·ui·架构
jctech10 小时前
让「小程序」跑起真正的原生代码:ComboNative 多进程原生小程序运行时 · Alpha 首发
android·设计模式·架构
Helen_cai10 小时前
OpenHarmony 通用状态加载、空页面、错误兜底组件封装(全局业务通用 UI 组件 API23)
开发语言·ui·华为·php·harmonyos
YM52e11 小时前
鸿蒙 Flutter BoxDecoration装饰:打造精美UI效果
学习·flutter·ui·华为·harmonyos·鸿蒙
qq_4634084211 小时前
# 基于 HarmonyOS ArkTS 声明式 UI 构建智能音乐播放器:深色主题圆盘轮播、五 Tab 导航隔离、瀑布流收藏与悬浮迷你播放条实现深度解析
ui·华为·harmonyos
Kel1 天前
Node.js 单线程高并发:从内核中断到 JS 回调的完整技术栈
设计模式·架构·node.js
工业HMI实战笔记1 天前
【无标题】
大数据·人工智能·ui·自动化·人机交互·交互
帅次1 天前
Kotlin Flow 与 StateFlow:UI 单向数据流基础
开发语言·ui·kotlin·stateflow·onlifecycle