一杯咖啡带你读懂状态机

Wyc Wyc     2022-09-07     717

关键词:

 状态机的简单介绍

最近公司做棋牌的项目,当时还是不理解什么是状态机,当一个项目做完之后,大脑里已经有了一个状态机的概念,所以今天就与大家分享出来,由于本人的技术博浅,有很多地方没有理解通透的地方,请望大神指点,抱拳了。

什么是状态机?

我理解的状态机就是,当一个事件触发之后,就会去寻找一个相对应的大的状态,然后在到大的状态里去寻找小的状态,然后执行完毕,给用户返回。

可能本人理解的不是多通透,在此边查资料边学习,与大家一起分享。

一丶状态模式

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

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

状态模式结构图

State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为

abstract class State
{
    public abstract void Handle(Context context) ; 
}
State类

ConcreteState类,具体状态,每一个子类实现以个与Context的一个状态相关行为

ConcreteState

Context类,维护一个ConcreteState子类的实列,这个实列定义当前的状态

class Context
{
    private State state;
    public Context (State state)        # 定义 Context的初始状态
    {
        this.state = state;
    }
    public State State        # 可读写的状态属性,用于读取当前状态和设置新状态
    {
        get ( return state ;)
        set
        {
  
            state = value;
            Console.WriteLine("当前状态:" + state.GetType().Name);
        }
    }
    public void Request()
    {
        state.Handle(this);            # 对请求做处理,并设置下一状态
    }
}                
Context类

客户端代码

state void Main (string[] args)
{
     Context c  = new Context(new ConcreteStateA());     # 设置Context的初始状态为ConcreteStateA

    c.Request();
    c.Request();
    c.Request();
    c.Request();            # 不断请求,同事更改状态


    
    Console.Read();
}
客户端代码

状态模式的好处与坏处

状态模式的好处是将于特定状态相关的行为局部化,并且将不同的状态的行为分割开来。

将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在与某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。

这样做的目的是什么?

这样做的目的说白了就是为了消除庞大的条件分之语句,大的分之判断会使得它们难以修改和扩展,就想刻板和印刷一样,任何改动都是致命的,状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互依赖,好比把整个版面改成一个又一个的活字,此时候就容易维护和扩展了。

什么时候应该考虑使用状态模式呢?

当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。

参考设计模式举例 - 工作状态

代码结构图

 

抽象状态类,定义一个抽象方法"写程序"

public abstract class State
{
    public abstract void WriteProgram(Work w);
}
抽象状态类

上午和中午工作状态类

pulic class ForenoonState : State
{
    public override void WriteProgram  (Work w)
    {
        if (w.Hour < 12) {
             Console.WriteLine("当前时间: {0}点 上午工作,精神百倍",w.Hour);
        }
        else
        {
             w.SetState(new NoonState());w.WriteProgram();
             # 超过12点,则转入中午工作状态
        }
    }
}
上午工作状态类
public class NoonState : State
{
    public override void WriteProgram(Work w)
   {
        if (w.Hour < 13){
            Console.WriteLine("当前时间: {0}点 饿了,午饭:犯困,午休。", w.Hour);
       }
       else
        {
             w.SetState (new AfternoonState());w.WriteProgram();
              # 超过13点则转入下午工作状态
        }
    }
}
中午工作状态

下午和傍晚工作状态类

public class AfternoonState : State
{
    public override void WriteProgram (Work w)
    {
     if (w.Hour < 17)
     {
          Console.WriteLine("当前时间:{0}点 下午状态还不错,继续努力", w.Hour;)
     }
     else
      {
           w.SetState(new EveningState());
           # 超过17点,则转入傍晚工作状态
           w.WriteProgram();
      }
    }
}
下午工作状态
public class EveningState : State
{
    public override void WriteProgram(Work w)
    {
         if (w.TaskFinished)
         {
              w.SetState(new RestState());
               # 如果完成任务,则转入下班状态
              w.WriteProgram();
         }
         else
         {
              w.SetState(new SleepingState()); w.WriteProgram();
             # 超过21点,则转入睡眠工作状态  
         }
    }
}
晚间工作状态

睡眠状态和下班休息状态类

public class SleepingState : State
{
    public override void WriteProgram(Work w)
    {
        Console.WriteLine("当前时间:{0}点不行了,睡着了。", w.Hour);
    }
}
睡眠状态
public class RestState : State
{
    public override void WriteProgram(Work w)
    {

        Console.WriteLine("当前时间:{0}点下班回家了", w.Hour);
    }
}
下班休息状态

工作类

public class Work
{
    private State current;
    public Work()
    # 工作初始化为上午工作状态,即上午9点开始上班
    {
         current = new ForenoonState();
    }
    private double hour;
    public double Hour
   {# 终点属性,状态转换的依据
        get{return hour;}
        set{hour = value;}
    }
    private bool finish = false;
    public bool TaskFinished
    {# 任务完成属性,是否能下班的依据
         get{return finish}
         set{finish= value}
    }
    public void SetState(State s)
    {
        current = s;
    }
    public void WriteProgram()
    {
        current.WriteProgram(this);
    }

}
工作类

客户端代码

static void Main(string[] args);
{
    //紧急项目
    Work emergencyProjects = new Work();
    energencyProjects.Hour = 9;
    Work emergencyProjects = new Work();
    energencyProjects.Hour = 10;
    Work emergencyProjects = new Work();
    energencyProjects.Hour = 12;
    Work emergencyProjects = new Work();
    energencyProjects.Hour = 13;
    Work emergencyProjects = new Work();
    energencyProjects.Hour = 14;
    Work emergencyProjects = new Work();
    energencyProjects.Hour = 17;


     //emergencyProjects.WorkFinished = true;
    emergencyProjects.WorkFinished = false;

    Work emergencyProjects = new Work();
    energencyProjects.Hour = 19;

    Work emergencyProjects = new Work();
    energencyProjects.Hour = 22;

    Console.Read();
    
}
客户端代码

结果表现如下

1 当前时间:10点 上午工作, 精神百倍
2 当前时间:12点 饿了,午饭:犯困,午休
3 当前时间:13点 下午状态还不错,继续努力
4 当前时间:14点 下午状态还不错,继续努力
5 当前时间:17点 加班哦,疲劳之极
6 当前时间:19点 加班哦,疲劳之极
7 当前时间:22点 不行了,睡着了

状态机的理解,大概就是这样,从一个大的状态切换到一个小的状态。

一文带你读懂sdk测试

一.什么是SDKSDK,全称:softwaredevelopmentkit,软件开发工具包。软件开发工具包一般都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件时的开发工具的集合。软件开发工具广义上指辅助开... 查看详情

什么是mapreduce,一文带你读懂

什么是MapReduce?MapReduce是一种编程模型,用于大规模数据集的并行运算;是面向大数据并行处理的计算模型、框架和平台。MapReduce思想是什么?MapReduce的思想核心是“分而治之”。 所谓“分而治之”就是把一个复杂的... 查看详情

从源码入手,一文带你读懂springaop面向切面编程

之前《零基础带你看Spring源码——IOC控制反转》详细讲了Spring容器的初始化和加载的原理,后面《你真的完全了解Java动态代理吗?看这篇就够了》介绍了下JDK的动态代理。基于这两者的实现上,这次来探索下Spring的AOP原理。虽... 查看详情

顾嘉:5分钟带你读懂《在线》逻辑

互联网成了基础设施,是创新平台;数据成了生产资料,是自然资源;计算成了公共服务,是能源动力。——王坚:《在线》  在我的记忆里,云计算、物联网、大数据是近年来被媒体和产业界炒得最热的几个概念了。... 查看详情

linux-一篇带你读懂curlproxy代理模式(代码片段)

curl是一个很有名的处理网络请求的类Unix工具。出于某种原因,我们进行网络请求,需要设置代理。本文讲全面介绍如何为curl设置代理设置代理参数基本用法-x,--proxy[protocol://]host[:port]设置HTTP代理下面两种设置代理的方式... 查看详情

linux-一篇带你读懂curlproxy代理模式(代码片段)

curl是一个很有名的处理网络请求的类Unix工具。出于某种原因,我们进行网络请求,需要设置代理。本文讲全面介绍如何为curl设置代理设置代理参数基本用法-x,--proxy[protocol://]host[:port]设置HTTP代理下面两种设置代理的方式... 查看详情

带你读懂spring的事务传播行为(代码片段)

点击关注公众号,实用技术文章及时了解来源:blog.csdn.net/xuan_lu/article/details/106006755一、概念首先简单了解一下Spring中事务传播行为是什么?听起来很高端,但是真正用起来的时候,稍有不慎,就会让自己... 查看详情

[含有环境搭建]一篇带你读懂hbase(代码片段)

作者简介:大家好,我是?让我们一起共同进步吧!????个人主页:的csdn博客??系列专栏:??哲学语录:承认自己的无知,乃是开启智慧的大门??如果觉得博主的文章还不错的话,请点赞??+收藏+留言??... 查看详情

一篇带你读懂tcp之“滑动窗口”协议(代码片段)

前言你现在的努力,是为了以后有更多的选择。在上一篇文章通过“表白”方式,让我们快速了解网络七层协议了解了网络七层协议。接下来我们要把重心放在网络传输的可靠性上面。一起来看TCP协议,它是如何解决网络传输不... 查看详情

一篇带你读懂tcp之“滑动窗口”协议(代码片段)

前言你现在的努力,是为了以后有更多的选择。在上一篇文章通过“表白”方式,让我们快速了解网络七层协议了解了网络七层协议。接下来我们要把重心放在网络传输的可靠性上面。一起来看TCP协议,它是如何解决网络传输不... 查看详情

阿里面试必问:带你读懂binder通信机制;拿捏面试官(代码片段)

本文设计内容:结合视频掌握更快1.准备2.为什么会有Binder通信机制3.面试系列4.为什么会有内核空间与用户空间5.内存管理单元6.Binder原理之前有个朋友小明1.2.3号去阿里面试的时候被问道一些关于Binder相关的内容,由于本... 查看详情

工业品mro采购网站有哪些优势?一文带你读懂

随着互联网电商的迅速发展,越来越多的工业品企业开始寻求新的突破口,很多MRO商城网站应运而生,这种“互联网+工业”的新型数字化采购模式,能够将数字能力及技术优势贯穿企业管理全流程,让品类... 查看详情

3000字带你读懂:bi能解决报表解决不了的什么问题?

一、BI不等于报表工作原因,老李经常跟不同行业的人打交道。不聊不知道,在大肆谈论“数字化转型”、“信创”、“业务对象数字化”、“BI”这类大而广的词语之下,隐藏着的却是国人的无知。搞业务的朋友不... 查看详情

spl-一篇带你读懂从jsonpath和xpath到spl(代码片段)

XML和Json不仅是结构化文本,而且擅长表示多层数据,可承载足够通用和足够丰富的信息,因此常被用于各种数据交换和信息传递事务,比如WebService/Restful,微服务等。但多层数据要比传统的二维表结构复杂... 查看详情

linux疑难杂症解决方案100篇(二十)-万字长文带你读懂正则表达式(建议收藏)

...自行订阅,你的支持就是我不断更新的动力哟!MATLAB-30天带你从入门到精通MATLAB深入理解高级教程(附源码)tableau可视化数据分析高级教程正则表达式百度百科里写到:正则表达式又称规则表达式,计 查看详情

一文带你读懂dockerfile(代码片段)

目录一、概述二、DockerFile构建过程解析(一)Dockerfile内容基础知识(二)Docker执行Dockerfile的大致流程(三)总结三、DockerFile常用保留字指令四、案例(一)自定义镜像mycentosjava8(二)虚... 查看详情

五分钟带你读懂uml类图

参考技术A目录先看下面这张类图,包括了UML类图的基本图示法 1、类的表示 2、接口的表示3、继承关系4、实现接口5、关联关系6、聚合关系7、合成(组合)关系8、依赖关系先看下面这张类图,包括了UML类图的基本图示法... 查看详情

各行各业都在关注的“密评”到底是啥?一文带你读懂!

...f1a;今天我们就来讲讲关于“密评”的那些事儿,一文带你搞懂“密评”!本文分享自华为云社区《各行各业都在关注的“密评”到底是啥?一文带你读懂!》,作者:开天aPaaS小助手。要说2022年各行各业... 查看详情