(三)行为模式:8、状态模式(State Pattern)(C++示例)

目录

1、状态模式(State Pattern)含义

2、状态模式的UML图学习

3、状态模式的应用场景

4、状态模式的优缺点

(1)优点

(2)缺点

5、C++实现状态模式的实例


1、状态模式(State Pattern)含义

状态模式(State),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。【DP】

状态模式主要解决的是,当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,那就没必要用‘状态模式’了 。“

2、状态模式的UML图学习

状态模式主要涉及以下几个角色:

(1)环境(Context):环境类是拥有状态的对象,它维护一个对抽象状态类的引用,通过该引用来切换当前状态。环境类在其操作中会委托给当前状态对象进行处理。

(2)抽象状态(State):抽象状态类定义了一个接口,用于封装环境对象的特定状态所对应的行为。

(3)具体状态(Concrete State):具体状态类实现了抽象状态类定义的接口,并根据具体情况进行相应的处理和状态转换。

通过这些角色的协作,状态模式可以实现对象的状态与行为之间的解耦,使得状态的变化不会影响到客户端代码,同时也方便了状态的扩展和维护。

3、状态模式的应用场景

(1)一个对象的行为取决于它的状态,并且需要在运行时根据状态改变行为时,可以考虑使用状态模式。

(2)当一个对象的行为在不同的状态下有不同的实现,且这些状态可以动态切换时,可以考虑使用状态模式。

(3)当需要消除大量的条件判断语句,并将其转换为状态类之间的关联时,可以考虑使用状态模式。

4、状态模式的优缺点

(1)优点

        1)将状态转换逻辑封装在具体的状态类中,使得状态变化对于客户端来说是透明的,客户端无需关心状态的切换细节。

        2)将大量的条件判断语句转换为状态类之间的关联,使得代码更加清晰、可读性更高。

        3)符合开闭原则,当需要增加新的状态时,只需要添加新的状态类而不需要修改现有的代码。

简而言之:"是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来【DP】"

(2)缺点

        1)状态模式会引入多个状态类,增加了系统的复杂性。 

        2)如果状态转换比较复杂,可能会导致状态类之间的相互调用增多,影响系统的性能。

5、C++实现状态模式的实例


#include <iostream>

// 状态接口
class State 
{
public:
    virtual void handle() = 0;
};

// 具体状态类A
class ConcreteStateA : public State 
{
public:
    void handle() override 
    {
        std::cout << "Handle by ConcreteStateA" << std::endl;
    }
};

// 具体状态类B
class ConcreteStateB : public State 
{
public:
    void handle() override 
    {
        std::cout << "Handle by ConcreteStateB" << std::endl;
    }
};

// 上下文类
class Context 
{
private:
    State* state;

public:
    Context(State* initialState) : state(initialState) {}

    void setState(State* newState) 
    {
        state = newState;
    }

    void request() 
    {
        state->handle();
    }
};

int main() {

    // 创建状态对象
    State* stateA = new ConcreteStateA();
    State* stateB = new ConcreteStateB();

    // 创建上下文对象并设置初始状态
    Context context(stateA);

    // 请求处理
    context.request();  // 输出: Handle by ConcreteStateA


    // 切换状态
    context.setState(stateB);
    context.request();  // 输出: Handle by ConcreteStateB


    // 释放资源
    delete stateA;
    delete stateB;

    return 0;
}

上述示例中,定义了一个状态接口State,具体状态类ConcreteStateAConcreteStateB实现了该接口。上下文类Context持有一个状态对象,并根据当前状态调用相应的行为。通过切换状态,可以改变上下文对象的行为。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的状态模式示例: ```C #include <stdio.h> // 状态接口 typedef struct State State; struct State { void (*handle)(State*); }; // 具体状态A typedef struct StateA StateA; struct StateA { State state; // 继承自状态接口 int count; // 计数器 }; void StateA_handle(State* super) { StateA* self = (StateA*) super; // 获取自身 printf("这是状态A,当前计数:%d\n", self->count++); } StateA* StateA_new() { StateA* self = (StateA*) malloc(sizeof(StateA)); // 分配内存 self->state.handle = StateA_handle; // 设置状态处理函数 self->count = 0; // 初始化计数器 return self; } // 具体状态B typedef struct StateB StateB; struct StateB { State state; // 继承自状态接口 int count; // 计数器 }; void StateB_handle(State* super) { StateB* self = (StateB*) super; // 获取自身 printf("这是状态B,当前计数:%d\n", self->count++); if (self->count == 3) { // 转移状态 free(self); // 释放内存 self = StateA_new(); // 创建新状态对象 } } StateB* StateB_new() { StateB* self = (StateB*) malloc(sizeof(StateB)); // 分配内存 self->state.handle = StateB_handle; // 设置状态处理函数 self->count = 0; // 初始化计数器 return self; } // 环境类 typedef struct Context { State* state; // 当前状态 } Context; Context* Context_new() { Context* self = (Context*) malloc(sizeof(Context)); // 分配内存 self->state = (State*) StateB_new(); // 初始化状态为B return self; } void Context_request(Context* self) { self->state->handle(self->state); // 调用当前状态的处理函数 } // 测试程序 int main() { Context* context = Context_new(); // 创建环境对象 for (int i = 0; i < 5; i++) { // 循环调用状态处理函数 Context_request(context); } free(context->state); // 释放内存 free(context); return 0; } ``` 运行结果如下: ``` 这是状态B,当前计数:0 这是状态B,当前计数:1 这是状态B,当前计数:2 这是状态A,当前计数:0 这是状态A,当前计数:1 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值