C++设计模式之状态模式

发布时间:2024年01月24日

【声明】本题目来源于卡码网(卡码网KamaCoder

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分


设计模式大纲】


【简介】

? ? ? ? --什么是状态模式(第20种设计模式)

????????状态模式(State Pattern)是?种行为型设计模式,它适?于?个对象在不同的状态下有不同的行为时,?如说电灯的开、关、闪烁是不停的状态,状态不同时,对应的行为也不同,在没有状态模式的情况下,为了添加新的状态或修改现有的状态,往往需要修改已有的代码,这违背了开闭原则,而且如果对象的状态切换逻辑和各个状态的行为都在同?个类中实现,就可能导致该类的职责过重不符合单?职责原则
????????而状态模式将每个状态的行为封装在?个具体状态类中,使得每个状态类相对独?,并将对象在不同状态下的行为进?委托,从而使得对象的状态可以在运行时动态改变,每个状态的实现也不会影响其他状态。


【基本结构】

????????状态模式包括以下?个重要角色:

  • State (状态): 定义?个接口,?于封装与Context的?个特定状态相关的?为。
  • ConcreteState (具体状态): 负责处理Context在状态改变时的?为, 每?个具体状态?类实现?个与Context 的?个状态相关的?为。
  • Context (上下?): 维护?个具体状态?类的实例,这个实例定义当前的状态。

【基本实现】

1. 定义状态接口:

????????创建?个状态接?,该接?声明了对象可能的各种状态对应的?法。

// 状态接?
public interface State {
    void handle();
}


2. 实现具体状态类:

????????为对象可能的每种状态创建具体的状态类,实现状态接?中定义的?法。

// 具体状态类1
public class ConcreteState1 implements State {
    @Override
    public void handle() {
        // 执?在状态1下的操作
    }
}
// 具体状态类2
public class ConcreteState2 implements State {
    @Override
    public void handle() {
        // 执?在状态2下的操作
    }
}


3. 创建上下文类:

????????该类包含对状态的引用,并在需要时调?当前状态的?法。

// 上下?类
public class Context {
    private State currentState;

    public void setState(State state) {
        this.currentState = state;
    }

    public void request() {
        currentState.handle();
    }
}

4. 客户端使用:

????????创建具体的状态对象和上下文对象,并通过上下文对象调用相应的?法。通过改变状态,可以改变上下?对象的行为

public class Client {
    public static void main(String[] args) {
        Context context = new Context();

        State state1 = new ConcreteState1();
        State state2 = new ConcreteState2();

        context.setState(state1);
        context.request(); // 执?在状态1下的操作

        context.setState(state2);
        context.request(); // 执?在状态2下的操作
    }
}

【使用场景】

????????状态模式将每个状态的实现都封装在?个类中,每个状态类的实现相对独?,使得添加新状态或修改现有状态变得更加容易,避免了使??量的条件语句来控制对象的行为。但是如果状态过多,会导致类的数量增加,可能会使得代码结构复杂。
????????总的来说,状态模式适用于有限状态机的场景,其中对象的?为在运?时可以根据内部状态的改变?改变,在游戏开发中,Unity3D 的 Animator 控制器就是?个状态机。它允许开发?员定义不同的状态(动画状态),并通过状态转换来实现角色的动画控制和?为切换。


【C++编码部分】

1. 题目描述

????????小明家有一个灯泡,刚开始为关闭状态(OffState)。台灯可以接收一系列的指令,包括打开("ON")、关闭("OFF")和闪烁("BLINK")。每次接收到一个指令后,台灯会执行相应的操作,并输出当前灯泡的状态。请设计一个程序模拟这个灯泡系统。

2. 输入描述

????????第一行是一个整数 n(1 <= n <= 1000),表示接收的命令数量。?接下来的 n 行,每行包含一个字符串 s,表示一个命令("ON"、"OFF"或"BLINK")。

3. 输出描述

????????对于每个命令,输出一行,表示执行该命令后灯泡的状态。

4. C++编程实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file StateMode.hpp
* @brief 状态模式
* @autor 写代码的小恐龙er
* @date 2024/01/24
*/

#include <iostream>
#include <string>

using namespace std;

// 前置声明

//  状态接口 类
class State;

// 具体状态1 -- 打开
class StateOn;
// 具体状态2 -- 关闭
class StateOff;
// 具体状态3 -- 闪烁
class StateBlink;

// 上下文类 -- 关注的对象类 灯
class Light;

//  状态接口 类
class State{
// 成员接口函数
public:
    virtual string Handle() = 0;
};

// 具体状态1 -- 打开
class StateOn : public State
{
// 重载接口函数
public:
    string Handle() override{
        return "Light is ON";
    }
};

// 具体状态2 -- 关闭
class StateOff : public State
{
// 重载接口函数
public:
    string Handle() override{
        return "Light is OFF";
    }
};

// 具体状态3 -- 闪烁
class StateBlink : public State
{
// 重载接口函数
public:
    string Handle() override{
        return "Light is Blinking";
    }
};

// 上下文类 -- 关注的对象类 灯
class Light{
// 成员数据
private:
    // 灯的状态
    State *_state = nullptr;
// 成员函数 
public:
    // 构造函数
    Light(){
        this->_state = new StateOff();
    }
    
    // 设置状态
    void SetState(State *state){
        this->_state = state;
    }
    
    // 执行操作
    string HandleState(){
        return _state->Handle();
    }
};

int main()
{
    // 命令数量
    int orderNum = 0;
    std::cin >> orderNum;
    // 创建 上下文类 -- 灯泡
    Light *light = new Light();
    // 创建 状态基类
    State *state = nullptr;
    // 遍历输入
    for(int i = 0; i < orderNum; i++){
        // 指令类型
        string orderType = "";
        std::cin >> orderType;
        
        // 判断
        if(orderType == "ON"){
            state = new StateOn();
        }
        else if(orderType == "OFF"){
            state = new StateOff();
        }
        else if(orderType == "BLINK"){
            state = new StateBlink();
        }
        
        // 给灯设置状态
        light->SetState(state);
        // 打印信息
        string printInfo = light->HandleState();
        std::cout << printInfo << endl;
    }
    
    // 析构!
    delete light;
    light = nullptr;
    
    if(state != nullptr){
        delete state;
        state = nullptr;
    }

    return 0;
}


......

To be continued.

文章来源:https://blog.csdn.net/K1_uestc/article/details/135818473
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。