[因为我不懂啊]-什么是状态机编程(设计模式)(1)

本阶段对状态机编程的理解:

  • 把物体的操作逻辑分为几个状态,每个状态有对应的处理
  • 操作时,只需要去改变物体状态即可,物体会自动根据状态执行对应的处理

这段理解放入示例中是这样的:

  • 电梯有四个状态:开门、关门、运动、停止
  • 电梯在达到某个状态时,会输出对应的log作为处理
  • 电梯对外有一个goto指定楼层的接口

下面来详细设计一下相关的内容

  • 状态[枚举]
    - 开门
    - 关门
    - 运动
    - 静止

  • 电梯[类]
    - 状态标志[变量]
    - 设置状态[方法]
    - 开门的处理[方法]
    - 关门的处理[方法]
    - 运动的处理[方法]
    - 停止的处理[方法]

    - 移动到楼层[方法]
    - 当前楼层[变量]
    - 目标楼层[变量]
    

实现代码:

//
//  ElevatorOne.hpp
//  QFLTest
//
//  Created by QuFangliu on 16/9/18.
//
//

/*
    电梯测试_1
 
    运行逻辑:
        停止->开门(进入)->关门->运动->停止->开门(离开)->关门
 
    ????我tm写的什么
 
 
 */

#ifndef ElevatorOne_hpp
#define ElevatorOne_hpp

#include <stdio.h>

enum ElevatorOneState
{
    State_Opening   = 1,    //电梯门打开状态
    State_Closing   = 2,    //电梯门关闭状态
    State_Running   = 3,    //电梯运动状态
    State_Stopping  = 4     //电梯静止状态
};

class ElevatorOne
{
public:
    ElevatorOne();
    virtual ~ElevatorOne();
    
public:
    void gotoFloor(int nFloor);
    
private:
    void setState(ElevatorOneState eState); //只能通过事件来改变电梯的状态,电梯自动运行
    
    void open();    //开门
    void close();   //关门
    void run();     //运动
    void stop();    //减速到停止
    
private:
    ElevatorOneState m_eState;  //电梯状态标志
    int m_nTargetFloor;         //电梯目标楼层
    int m_nFloor;               //电梯所在楼层
};

#endif /* ElevatorOne_hpp */
//
//  ElevatorOne.cpp
//  QFLTest
//
//  Created by QuFangliu on 16/9/18.
//
//

#include "ElevatorOne.hpp"
#include <iostream>

#define QFLLOG(_text_)  do  \
                        {   \
                            std::cout << _text_ << std::endl;   \
                        } while (false) \

ElevatorOne::ElevatorOne()
{
    m_eState = ElevatorOneState::State_Stopping;    //默认静止状态
    m_nFloor = 1;                                   //默认楼层1楼
    m_nTargetFloor = 1;                             //默认目标1楼
}

ElevatorOne::~ElevatorOne()
{
    
}

//操作
void ElevatorOne::gotoFloor(int nFloor)
{
    if (m_nTargetFloor == nFloor) {
        //不需要运动
        QFLLOG("Elevator is here.");
    }
    else {
        //设置目标楼层
        m_nTargetFloor = nFloor;
        //状态转换
        this->setState(ElevatorOneState::State_Opening);
    }
}

//状态转换
void ElevatorOne::setState(ElevatorOneState eState)
{
    m_eState = eState;
    
    switch (eState) {
        case State_Opening:
            this->open();
            break;
        case State_Closing:
            this->close();
            break;
        case State_Running:
            this->run();
            break;
        case State_Stopping:
            this->stop();
            break;
        default:
            break;
    }
}

//运行逻辑
//开门
void ElevatorOne::open()
{
    QFLLOG("Elevator open...");
    
    //下一个状态必然是close
    this->setState(ElevatorOneState::State_Closing);
}
//关门
void ElevatorOne::close()
{
    QFLLOG("Elevator close...");
    
    //根据目标楼层,判断进入怎样的状态
    if (m_nFloor != m_nTargetFloor) {
        this->setState(ElevatorOneState::State_Running);
    }
    else {
        //结束状态
    }
}
//运行
void ElevatorOne::run()
{
    QFLLOG("Elevator run..." << m_nTargetFloor);
    
    //移动到对应的楼层
    m_nFloor = m_nTargetFloor;
    
    //下一个状态必然是stop
    this->setState(ElevatorOneState::State_Stopping);
}
//静止
void ElevatorOne::stop()
{
    QFLLOG("Elevator stop...");
    
    //下一个状态必然是open
    this->setState(ElevatorOneState::State_Opening);
}

上面就是Elevator的完整逻辑代码,运行测试过程代码如下,直接放在 int main(void)中即可,我示例中是写在按钮的触发事件中。

    //elevator
    auto pElevator = new ElevatorOne();
    pElevator->gotoFloor(20);
    pElevator->gotoFloor(20);//移动到本层试试

输出结果:
Elevator open...
Elevator close...
Elevator run...20
Elevator stop...
Elevator open...
Elevator close...
Elevator is here.


总结:
1.我不知道为什么要写一个gotoFloor的函数,只是觉得在测试中直接去写setState会很别扭,不符合正常控制过程(虽然在其他的博客中看到的关于FSM的实例代码,调用时都是直接写了几个setState)。
2.虽然这里有区分4个状态,每个状态也有对应的处理函数。但是我觉得这里使用状态并没有什么用。因为[使用setState转移到下一个状态],都可以直接用[下一个状态的处理函数]来替换。也就是说
//状态转换 this->setState(ElevatorOneState::State_Opening);
可以直接使用
//状态转换 this->open();
来代替。


求懂FSM的小伙伴评论指点。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容