设计模式学习(六) 状态模式


这是个人学习编程模式的系列学习笔记第六篇。
采用Qt Creator进行编写,但尽量采用C++基础语法。
状态模式(Stat Pattern):允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
这种模式主要是用于处理两类情况:
1、有大量的ifelseif的判断,这样的写法不利于代码的维护和修改,如果有新的修改,对一大片这样的判断代码进行修改,容易引入新的问题。
2、有类似状态机这样的业务场景,根据不同的状态,需要执行不同的操作。
比较典型的例子是TCP协议连接。对TCP连接发起指令时,根据当期TCP连接的状态,会执行不同的处理。
个人理解,通过将一个具有复杂判断行为的方法,通过根据不同判断条件(或者状态),将不同的处理方式封装为独立的类,这样就可以保持代码的封闭-开发原则,并每个方法聚焦于单一任务。
在具体实现上,可设计一个状态抽象类作为接口,然后派生各个状态下的子类,每个子类只处理自己状态下的情况。然后定义一个上下文(context)类,这个类负责状态的切换和对应状态子类方法的调用。

场景描述

设想有一个农场主,在不同的季节干不同的活。一年有四季,春季播种,夏季浇水,秋季收获,冬季休息。3、4、5月是春季,6、7、8月是夏季,9、10、11月是秋季,12、13、14月是冬季。
设计一个机器人帮农场主来完成这份工作。

设计思路

设计一个抽象类,定义干活这个接口。由这个类派生4个子类,分别是春季、夏季、秋季和冬季。
定义一个农场机器人,这个机器人自动根据季节干活。这个机器人会包含一个状态类的指针,和状态标识,根据状态标识,调用对应的状态,并完成对应的工作。

UML

在这里插入图片描述

代码

#include <iostream>
using namespace std;

enum seasons {Spr = 1, Sum, Aut, Win};
class FarmRobot;
class Season
{
public:
    virtual void doWork(FarmRobot* robot) = 0;
};
class FarmRobot
{
public:
    Season* m_stat = 0;
    seasons m_season;

    FarmRobot(Season* stat, seasons season):m_stat(stat),m_season(season){}
    ~FarmRobot() {delete m_stat;}

    void setStat(Season* stat)
    {
        delete m_stat;
        m_stat = stat;
    }
    void doWork()
    {
        if(m_stat) m_stat->doWork(this);
    }
};

class Winter : public Season
{
public:
    void doWork(FarmRobot* robot);
};

class Autumn : public Season
{
public:
    void doWork(FarmRobot* robot)
    {
        cout<<"Autumn:  I'm harvesting!\n";
        robot->setStat(new Winter());
    }
};

class Summer : public Season
{
public:
    void doWork(FarmRobot* robot)
    {
        cout<<"Summer:  I'm watering!\n";
        robot->setStat(new Autumn());
    }

};

class Spring : public Season
{
public:
    void doWork(FarmRobot* robot)
    {
        cout<<"Spring:  I'm sowing!\n";
        robot->setStat(new Summer());
    }
};
//将Winter的函数实现放在最后,是为避免循环引用,否则编译出错
void Winter::doWork(FarmRobot* robot)
{
    cout<<"Winter:  I'm resting!\n";
    robot->setStat(new Spring());
}

int main()
{
    FarmRobot* robot = new FarmRobot(new Spring, Spr);
    for(int s = Spr; s <= Win; s++)
    {
        robot->doWork();
    }
    delete robot;

    return 0;
}

运行结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值