专栏首页Python研发一杯咖啡带你读懂状态机

一杯咖啡带你读懂状态机

 状态机的简单介绍

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

什么是状态机?

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

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

一丶状态模式

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

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

状态模式结构图

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

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

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);            # 对请求做处理,并设置下一状态
    }
}                

客户端代码

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点 不行了,睡着了

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • HTML

    一个完整的网页是由HTML(超文本标记语言),css(层叠样式表)JavaScript(动态脚本语言)三部分组成.

    Wyc
  • 程序中的异步和同步

    同步:   主机A发送数据的时候,主机B必须等待接收,处于阻塞状态,这就好比别人给你打电话,你必须当场听话,否则则【错失良机】。

    Wyc
  • 网络编程socket

    socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

    Wyc
  • FastDFS并发会有bug,其实我也不太信?- 一次并发问题的排查经历

    前一段时间,业务部门同事反馈在一次生产服务器升级之后,POS消费上传小票业务偶现异常,上传小票业务有重试机制,有些重试三次也不会成功,他们排查了一下没有找到原因...

    纯洁的微笑
  • 三分种基础知识:计算机是如何存储浮点数的?

    相比int等整型,float等浮点类型的表示和存储较为复杂,但它又是一个无法回避的话题,那么就有必要对浮点一探究竟了。在计算机中,一般用IEEE浮点近似表示任意...

    帅地
  • 对浮点数的一些理解

    相比int等整型,float等浮点类型的表示和存储较为复杂,但它又是一个无法回避的话题,那么就有必要对浮点一探究竟了。在计算机中,一般用IEEE浮点近似表示任意...

    编程珠玑
  • 浮点数在计算机中是如何表示的

    相比int等整型,float等浮点类型的表示和存储较为复杂,但它又是一个无法回避的话题,那么就有必要对浮点一探究竟了。在计算机中,一般用IEEE浮点近似表示任意...

    编程珠玑
  • 【专知荟萃15】图像检索Image Retrieval知识资料全集(入门/进阶/综述/视频/代码/专家,附PDF下载)

    图像检索(Image Retrieval)专知荟萃 入门学习 进阶文章 综述 Tutorial 视频教程 代码 领域专家 Datasets 入门学习 相似...

    WZEARW
  • Spring Data之@Query中的org.hibernate.hql.internal.QueryExecutionRequestException: Not supported for DML

    Spring Data之@Query中的org.hibernate.hql.internal.QueryExecutionRequestException: N...

    一个会写诗的程序员
  • 深入理解xhr的responseType中blob和arrayBuffer

    版权声明:本文为吴孔云博客原创文章,转载请注明出处并带上链接,谢谢。 https://blog.csdn.net/wkyseo/articl...

    空空云

扫码关注云+社区

领取腾讯云代金券