一杯咖啡带你读懂状态机

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

 状态机的简单介绍

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

什么是状态机?

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

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

一丶状态模式

状态模式(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点 不行了,睡着了

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

相关文章
|
3月前
|
存储 算法 程序员
代码之韵:编程中的诗意与逻辑
在数字的世界里,每一行代码都如同诗句般细腻而富有节奏感。本文将探讨编程不仅仅是一门科学或技术,更是一种艺术形式,它融合了逻辑思维的严谨和创造力的灵动。我们将通过分析编程的核心概念,如变量、控制结构、函数等,来揭示它们背后的美学原则和哲学思考。同时,我们还将讨论如何在日常的编程实践中寻找和创造美感,以及这种美感如何影响我们的工作效率和产品的用户体验。
【期末不挂科-单片机考前速过系列P10】(第十章:11题中断系统的工作原理及应用)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P10】(第十章:11题中断系统的工作原理及应用)经典例题盘点(带图解析)
|
3月前
|
IDE 安全 程序员
揭秘如何用C编写出无敌的程序代码,你绝对会后悔错过!
揭秘如何用C编写出无敌的程序代码,你绝对会后悔错过!
26 1
|
3月前
|
API iOS开发
总是搞不懂的同步异步,阻塞非阻塞
总是搞不懂的同步异步,阻塞非阻塞
56 0
|
10月前
|
人工智能 程序员 vr&ar
竟有程序员40了还在撸代码?
竟有程序员40了还在撸代码?
118 2
|
Java 关系型数据库 MySQL
【浅尝高并发编程】接私活差点翻车
作为一名本本分分的练习时长两年半的Java练习生,一直深耕在业务逻辑里,对并发编程的了解仅仅停留在八股文里。一次偶然的机会,接到一个私活,核心逻辑是写一个 定时访问api把数据持久化到数据库的小服务。
158 0
|
存储 设计模式 缓存
揭秘通信协议设计的奥妙,作为面试官我都看蒙了
所谓的通信协议就是通信双方共同遵循的一种“约定”,用于通信发送方将内容按照“通信协议”所规定的格式组装成**“二进制流”**,通信接收方按照“通信协议”所规定的格式正确的从二进制流中解码出一个个原始请求。
|
XML 数据可视化 安全
给 DSL 开个脑洞:无状态的状态机
什么是 DSL ?DSL 是一种工具,其核心价值在于提供了一种手段,可以更加清晰地就系统某部分的意图进行沟通。本文将通过实现一个状态机引擎来看清 DSL 的本质,介绍状态机的核心模型和 Fluent 接口,并解决状态机的性能问题。
1689 0
给 DSL 开个脑洞:无状态的状态机
|
安全 Java
老爷子这代码,看跪了! (下)
老爷子这代码,看跪了! (下)
117 0
老爷子这代码,看跪了! (下)
|
Java 程序员
老爷子这代码,看跪了! (中)
老爷子这代码,看跪了! (中)
129 0
老爷子这代码,看跪了! (中)