做产品网站需要注意,wordpress 网站播放器插件,为什么选择当网站设计人员,广告设计专业学校有哪些很多业务系统开发中#xff0c;不可避免的会出现状态变化#xff0c;通常采用的情形可能是使用工作流去完成#xff0c;但是对于简单场景下#xff0c;用工作流有点大财小用感觉#xff0c;比如订单业务中#xff0c;订单状态的变更#xff0c;涉及到的状态量不是很多不可避免的会出现状态变化通常采用的情形可能是使用工作流去完成但是对于简单场景下用工作流有点大财小用感觉比如订单业务中订单状态的变更涉及到的状态量不是很多即使通过简单的if-else也能足够使用甚至是用上switch去减少if-else的使用都是可以的尽管这会丧失某些东西。为更好的优化整个流程此时会考虑到使用状态模式来解决一些问题。 Stateless状态机GitHubhttps://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建模中常常可见用来描述一个特定的对象所有可能的状态,以及由于各种事件的发生而引起的状态之间的转移和变化也是配置状态机按照何种行径的前提 。 二、Stateless功能介绍 Stateless是一个基于C#创建状态机的简单库。基于.Net Standard实现在.Net Framework和.Net Core项目中都可以使用。源码地址https://github.com/dotnet-state-machine/stateless。 以一个打电话的使用案例来讲讲Stateless的功能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的子状态对于进入和退出事件的处理者可以传参提供触发动作现状和次状信息。 4、外部状态存储 有时候当前对象的状态需要来自于一个ORM对象或者需要将当前对象的状态保存到一个ORM对象中UI框架需要存储一个状态到绑定属性中。为了支持这种外部状态存储StateMachine类的构造函数支持了读写状态值。如代码里通过使用myState可以去存储和获取状态值。var stateMachine new StateMachineState, Trigger( () myState.Value, s myState.Value s); 5、内省 该状态机可以通过StateMachine.PermittedTriggers属性获取当前状态下可以触发的触发器列表。并能够使用StateMachine.GetInfo()获取状态相关的配置信息。public IEnumerableTTrigger 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.SetTriggerParametersstring(Trigger.Assign);stateMachine.Configure(State.Assigned) .OnEntryFrom(assignTrigger, email OnAssigned(email));stateMachine.Fire(assignTrigger, joeexample.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中解析的状态机图形。 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