.Net轻量状态机Stateless

  很多业务系统开发中,不可避免的会出现状态变化,通常采用的情形可能是使用工作流去完成,但是对于简单场景下,用工作流有点大财小用感觉,比如订单业务中,订单状态的变更,涉及到的状态量不是很多,即使通过简单的if-else也能足够使用,甚至是用上switch去减少if-else的使用,都是可以的,尽管这会丧失某些东西。为更好的优化整个流程,此时会考虑到使用状态模式来解决一些问题。

  Stateless状态机GitHub:https://github.com/dotnet-state-machine/stateless  

一、状态模式与状态机

1、状态模式:"允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它所属的类 "。(State Pattern: "Allow an object to alter its behavior when its internal state changes. The object will appear to change its class ".)

  对于这个定义,有点抽象,变通理解一下可以这么理解:状态拥有者将变更行为委托给状态对象,状态拥有者本身只拥有状态(当然也可以抛弃状态对象),状态对象履行变更职责。

 

2、状态机:"依照指定的状态流程图,根据当前执行的动作,将当前状态按照预定的条件变更到新的状态 "。

  状态机有4个要素,即现态、条件、动作、次态。其中,现态和条件是“因”, 动作和次态是“果”。

  • 现态 - 是指当前对象的状态

  • 条件 - 当一个条件满足时,当前对象会触发一个动作

  • 动作 - 条件满足之后,执行的动作

  • 次态 - 条件满足之后,当前对象的新状态。次态是相对现态而言的,次态一旦触发,就变成了现态

 

3、状态迁移图:"在UML建模中,常常可见,用来描述一个特定的对象所有可能的状态,以及由于各种事件的发生而引起的状态之间的转移和变化,也是配置状态机按照何种行径的前提 "

  640?wx_fmt=png

 

二、Stateless功能介绍

  Stateless是一个基于C#创建状态机的简单库。基于.Net Standard实现,在.Net Framework和.Net Core项目中都可以使用。源码地址:https://github.com/dotnet-state-machine/stateless

  以一个打电话的使用案例来讲讲Stateless的功能:

640?wx_fmt=png


1、功能特性

 状态机常见功能:

  • 支持所有.Net类型的状态和触发器(数字、字符串、枚举等等)

  • 分层状态

  • 状态的进入和退出事件

  • 用卫语句来支持条件转换

  • 内省

 提供了一些有用的扩展:

  • 支持外部的状态存储(例如:由ORM跟踪属性)

  • 参数化触发器

  • 可重入状态

  • 导出DOT格式图

 

2、分层状态

  在以下例子中,OnHold状态是Connected状态的子状态。这意味着电话挂起的时候,还是连接状态的,通过IsInState()方法,可以判定是否当前状态处于父状态下的子状态,比如IsInState(State.Connected)能够返回true,说明当前OnHold状态是处于Connected状态的。

phoneCall.Configure(State.OnHold)
.SubstateOf(State.Connected)
.Permit(Trigger.TakenOffHold, State.Connected)
.Permit(Trigger.PhoneHurledAgainstWall, State.PhoneDestroyed);

 

3、状态的进入和退出事件

  在前面的例子中,StartCallTimer()方法会在通话连接时执行,StopCallTimer()方法会在通话结束时执行,对应的便是,进入该状态与脱离该状态时候执行的事件。当电话的状态从已连接(Connected)变为挂起(OnHold)时, 不会触发StartCallTimer()方法和StopCallTimer()方法, 这是因为OnHold是Connected的子状态,对于进入和退出事件的处理者,可以传参提供触发动作,现状和次状信息。

  640?wx_fmt=png

 

4、外部状态存储

  有时候,当前对象的状态需要来自于一个ORM对象,或者需要将当前对象的状态保存到一个ORM对象中,UI框架需要存储一个状态到绑定属性中。为了支持这种外部状态存储,StateMachine类的构造函数支持了读写状态值。如代码里,通过使用myState可以去存储和获取状态值。

var stateMachine = new StateMachine<State, Trigger>(
() => myState.Value,
s => myState.Value = s
);

 

5、内省

  该状态机可以通过StateMachine.PermittedTriggers属性获取当前状态下可以触发的触发器列表。并能够使用StateMachine.GetInfo()获取状态相关的配置信息。

public IEnumerable<TTrigger> PermittedTriggers
{
get
{
return GetPermittedTriggers();
}
}

//返回StateMachineInfo对象,包含状态及触发器列表。
_machine.GetInfo(); 

6、卫语句

  状态机将根据卫语句在多条转换线路之间进行选择,卫语句必须是互斥的,多个卫语句不能同时生效。子状态可以通过重新指定来覆盖状态转换,但是子状态不能覆盖父状态允许的状态转换,当触发器触发时,卫语句开始评估线路选择,因此不会带来其它方面的影响。

phoneCall.Configure(State.OffHook)
.PermitIf(Trigger.CallDialled, State.Ringing, () => IsValidNumber)
.PermitIf(Trigger.CallDialled, State.Beeping, () => !IsValidNumber)

 

7、参数化触发器

  支持将强类型参数提供给触发器,使用方法PermitDynamic()配置状态机时,能够通过触发器参数动态选择目标状态。

var assignTrigger = stateMachine.SetTriggerParameters<string>(Trigger.Assign);

stateMachine.Configure(State.Assigned)
.OnEntryFrom(assignTrigger, email => OnAssigned(email));

stateMachine.Fire(assignTrigger, "joe@example.com");

 

8、忽视转换和重入状态

  如果触发了一个没有配置过的线路,将会抛出一个异常,通过使用Ignore方法,忽视一些触发,当触发了此类触发器时,不会抛出异常,而改为忽略该次触发。

phoneCall.Configure(State.Connected)
.Ignore(Trigger.CallDialled);

  另外,一个状态能够使用PermitReentry方法配置为重复进入(从本状态到本状态),entry和exit事件也会被再次触发。

stateMachine.Configure(State.Assigned)
.PermitReentry(Trigger.Assigned)
.OnEntry(() => SendEmailToAssignee());

  默认情形下,必须明确忽略哪些触发器。当未配置的触发器被触发时默认是抛出异常,可以通过使用OnUnhandledTrigger配置状态机覆写处理异常情形。

stateMachine.OnUnhandledTrigger((state, trigger) => { });

 

9、导出DOT格式图

  运行状态可视化状态机是很有用处的,使用状态机时,代码是命令式的,而状态图是副产物。

phoneCall.Configure(State.OffHook)
.PermitIf(Trigger.CallDialled, State.Ringing, IsValidNumber);

string graph = UmlDotGraph.Format(phoneCall.GetInfo());

  UmlDotGraph.Format()方法返回代表状态机的字符串,使用DOT graph语言格式。这个可以被支持DOT graph语言的工具渲染。像graphviz.org和viz.js的dot command line工具。

  诸如生成的字符串在viz.js中解析的状态机图形。

  640?wx_fmt=png

 

10、异步触发

  该状态机支持异步操作,对于Entry/Exit方法等都有相应的异步方法,带Async结尾,并且对于触发也有异步方法FireAsync(),需要注意的是,尽管使用了异步,但仍然是单线程操作,不能被多个线程同时使用。

stateMachine.Configure(State.Assigned)
.OnEntryAsync(async () => await SendEmailToAssignee());

await stateMachine.FireAsync(Trigger.Assigned);

 至此,对于状态机Stateless的功能差不多了解完毕了,开始将状态机融入到项目中实际使用起来,也已经加入到日程中。

原文链接:https://www.cnblogs.com/CKExp/p/11564882.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/313175.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Asp.net Core全局异常监控和记录日志

前言系统异常监控可以说是重中之重&#xff0c;系统不可能一直运行良好&#xff0c;开发和运维也不可能24小时盯着系统&#xff0c;系统抛异常后我们应当在第一时间收到异常信息。在Asp.net Core里我使用拦截器和中间件两种方式来监控异常。全局异常监控的数据最好还是写入数据…

SiteServer CMS 新版本 V6.13(2019年11月1日发布)

欢迎来到 SiteServer CMS V6.13 版本&#xff0c;经过两个月的连续迭代开发&#xff0c;V6.13版本新增了几项重要功能&#xff0c;我们希望你会喜欢&#xff0c;一些关键的亮点包括&#xff1a;。新增功能及BUG 修复经过两个月的连续迭代开发&#xff0c;V6.13 版本新增了部分功…

CUDA的global内存访问的问题

http://blog.csdn.net/OpenHero/article/details/3520578 关于CUDA的global内存访问的问题&#xff0c;怎么是访问的冲突&#xff0c;怎样才能更好的访问内存&#xff0c;达到更高的速度。下面先看几张图&#xff0c;这些图都是CUDA编程手册上的图&#xff0c;然后分别对这些…

C# 8 新特性 - 异步流 Asynchronous Streams

异步流 Asynchronous Streams例子 这是一个很简单的控制台程序。它有一个NumberFactory&#xff0c;它可以根据传递的参数来产生一串数字&#xff08;IEnumerable<int>&#xff09;。然后在这个程序中把每个数字都打印出来&#xff0c;同时在前边显示出当前的线程ID。 这…

__syncthreads()

http://www.cnblogs.com/dwdxdy/p/3215136.html __syncthreads()是cuda的内建函数&#xff0c;用于块内线程通信. __syncthreads() is you garden variety thread barrier. Any thread reaching the barrier waits until all of the other threads in that block also reach i…

互联网50周年!这有它的一张“出生证明”

2019 年 10 月 29 日是互联网的 50 周年&#xff0c;50 年前(1969 年 10 月 29 日)&#xff0c;加州大学洛杉矶分校的计算机将一个只有两个字母(LO)的数据包发送到斯坦福研究所的计算机上&#xff0c;这是互联网史上的第一个数据包&#xff0c;从此开启互联网时代的第一步。 当…

Eltwise_layer简介

http://www.voidcn.com/blog/thy_2014/article/p-6117416.html common_layer&#xff1a; ArgMaxLayer类&#xff1b; ConcatLayer类&#xff1a; EltwiseLayer类&#xff1b; FlattenLayer类&#xff1b; InnerProductLayer类&#xff1b; MVNLayer类&#xff1b; SilenceLaye…

PowerBI 秒级实时大屏展示方案 全面助力双十一

双十一来了&#xff0c;你准备好了吗&#xff1f;不管你是否准备完毕&#xff0c;我们带来了全网首发的 PowerBI 秒级实时大屏展示方案&#xff0c;你可以直接用来展示双十一的实时状况。我们一步步来说明这个套件模板教程。真实效果功能如下&#xff1a;全实时展示 双十一 当天…

优化 .net core 应用的 dockerfile

优化 .net core 应用的 dockerfileIntro在给 .net core 应用的写 dockerfile 的时候一直有个苦恼&#xff0c;就是如果有很多个项目&#xff0c;在 dockerfile 里写起来就会很繁琐&#xff0c;有很多项目文件要 copy&#xff0c;dockerfile 还不支持直接批量复制项目文件&#…

C# 8 新特性 - 静态本地方法

从C# 8 开始&#xff0c;本地方法就可以是静态的了。 与其他的本地方法不同&#xff0c;静态的本地方法无法捕获任何本地状态量。 直接看例子&#xff1a; 这段代码里有两个本地方法&#xff0c;他们分别对实例的一个字段和方法里的一个本地变量进行了修改操作&#xff0c;也就…

​.NET手撸2048小游戏

前言2048是一款益智小游戏&#xff0c;得益于其规则简单&#xff0c;又和 2的倍数有关&#xff0c;因此广为人知&#xff0c;特别是广受程序员的喜爱。本文将再次使用我自制的“准游戏引擎” FlysEngine&#xff0c;从空白窗口开始&#xff0c;演示如何“手撸” 2048小游戏&…

自行实现高性能MVC

wcf虽然功能多、扩展性强但是也面临配置忒多&#xff0c;而且restful的功能相当怪异&#xff0c;并且目前没法移植。asp.net core虽然支持webapi&#xff0c;但是功能也相对繁多、配置复杂。就没有一个能让码农们安安心心的写webapi&#xff0c;无需考虑性能、配置、甚至根据问…

caffe matio问题

http://blog.csdn.net/houqiqi/article/details/46469981 注&#xff1a;如果指令行模式实在解决不了/lib/libcaffe.so: undefined reference to Mat_VarReadDataLinear问题&#xff0c;可以尝试在QT下进行训练和测试。 1&#xff0c; 下载matio(http://sourceforge.NET/pro…

技术管理者怎样跳出“泥潭”

近几年面试了不少新人&#xff0c;当问到职业规划时&#xff0c;大多都会说先积累技术&#xff0c;然后往架构师的方向发展。这可能是技术人的一个特质&#xff0c;喜欢跟机器相处&#xff0c;沉浸在代码之中&#xff0c;而不喜欢跟人打交道。现实的情况是&#xff0c;一些中小…

你或许以为你不需要领域驱动设计

作者&#xff1a;邹溪源&#xff0c;长沙资深互联网从业者&#xff0c;架构师社区合伙人&#xff01;一犹记得刚刚参加工作时&#xff0c;是地图厂商四维图新集团旗下的一家子公司&#xff0c;主要从事规划测绘相关软件研发的公司。当时我的项目是为勘测设计院提供相对应的应用…

redis为什么这么火该怎么用

最近一些人在介绍方案时&#xff0c;经常会出现redis这个词&#xff0c;于是很多小伙伴百度完redis也就觉得它是一个缓存&#xff0c;然后项目里面把数据丢进去完事&#xff0c;甚至有例如将实体属性拆分塞进redis hash里面的奇怪用法等等&#xff01;原因是什么呢&#xff1f;…

.Net Core实现健康检查

ASP.NET Core 提供运行状况检查中间件和库&#xff0c;以用于报告应用基础结构组件的运行状况。运行状况探测可以由容器业务流程协调程和负载均衡器用于检查应用的状态。例如&#xff0c;容器业务流程协调程序可以通过停止滚动部署或重新启动容器来响应失败的运行状况检查。负载…

微软宣布加入 OpenJDK,看网上各派的热闹

微软宣布加入 OpenJDK 项目&#xff08;https://www.oschina.net/news/111036/microsoft-to-participate-in-openidk&#xff09;&#xff0c;这两天在微信公众号里面有几种论调&#xff1a;上面这些都是Javaer的观点&#xff0c;在CSharper 对这件事情的反应更奇怪了&#xff…

这6点解释了罗永浩为什么要卖艺

01是的&#xff0c;我们的‘老赖又上热搜了。&#xff08;ps:还是传统的语法&#xff0c;换了个人而已&#xff0c;味道有点改变&#xff09;11 月 3 日下午&#xff0c;罗永浩因锤子科技的 375 万欠款被江苏丹阳法院限制高消费&#xff0c;他不得乘坐飞机头等舱、软卧、高铁等…

微软发布研究报告:企业数据管理普遍混乱,揭秘大数据分析趋势以及PowerBI的崛起机遇...

本文非常重要&#xff0c;忽略者责任自负。我们时常看到很多新闻说企业的数据分析或大数据如何如何高大上&#xff0c;但你自己感觉你自己所处的环境呢&#xff1f;很多小伙伴在群里真切的抱怨到&#xff1a;感觉是一坨祥云。为什么你看到的和你感受到的有如此巨大的反差&#…