用状态模式实现状态机工作流
概述
状态机工作流由一组状态组成。一个状态被指示为初始状态。每个状态都可以接收一组特定事件。视事件而定,可以转换到另一个状态。状态机工作流可以有最终状态。当转换到最终状态时,工作流将完成。
场景
针对我上篇博客设计的一个简单的状态机工作流,流程图如下:
我们来设计个用设计模式中的状态模式来设计这个工作流。
设计
先看看它的User Case功能设计:
再看看它的Class diagram设计:
实现
先创建Enums class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | /******************************************************************************** ** Class Name: Enums ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: Enums class *********************************************************************************/ using System; namespace WorkFlowCommon { public enum ApplicationState { None, Draft, InProgress, Complete, } public enum WorkFlowState { None, Common, Manager, Done, Refuse } [Flags] public enum ActivityState { Create=1, Edit=2, Resbmit=4, Submit=8, Revoke=16, Approve=32, Reject=64, Read=128, None=256 } } |
再创建IActivity Interface:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /******************************************************************************** ** Class Name: IActivity ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: IActivity interface *********************************************************************************/ namespace WorkFlowService.IDAL { using WorkFlowCommon; public interface IActivity { WorkFlowState Execute(ActivityState activityState); } } |
再创建IActivityState interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /******************************************************************************** ** Class Name: IActivityState ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: IActivityState interface *********************************************************************************/ namespace WorkFlowService.IDAL { using WorkFlowCommon; public interface IActivityState { ActivityState GetActivityState(); } } |
再创建IStateBase interface
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /******************************************************************************** ** Class Name: IStateBase ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: IStateBase interface *********************************************************************************/ namespace WorkFlowService.IDAL { using WorkFlowCommon; public interface IStateBase : IActivity, IActivityState { WorkFlowState GetCurrentState(); } } |
再创建CommonState class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | /******************************************************************************** ** Class Name: CommonState ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: CommonState class *********************************************************************************/ namespace WorkFlowService.DAL { using WorkFlowCommon; using IDAL; public class CommonState : IStateBase { public WorkFlowState Execute(ActivityState activityState) { if (activityState == ActivityState.Submit || activityState == ActivityState.Resbmit) return WorkFlowState.Manager; return WorkFlowState.Common; } public WorkFlowState GetCurrentState() { return WorkFlowState.Common; } public ActivityState GetActivityState() { return ActivityState.Submit | ActivityState.Read | ActivityState.Revoke | ActivityState.Resbmit; } } } |
再创建DoneState Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /******************************************************************************** ** Class Name: DoneState ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: DoneState class *********************************************************************************/ namespace WorkFlowService.DAL { using WorkFlowCommon; using IDAL; public class DoneState : IStateBase { public WorkFlowState Execute(ActivityState activityState) { return WorkFlowState.Done; } public WorkFlowState GetCurrentState() { return WorkFlowState.Done; } public ActivityState GetActivityState() { return ActivityState.Read; } } } |
再创建ManageState class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /******************************************************************************** ** Class Name: ManageState ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: ManageState class *********************************************************************************/ namespace WorkFlowService.DAL { using WorkFlowCommon; using IDAL; public class ManageState : IStateBase { public WorkFlowState Execute(ActivityState activityState) { if (activityState == ActivityState.Approve) return WorkFlowState.Done; if (activityState == ActivityState.Revoke) return WorkFlowState.Common; return WorkFlowState.Refuse; } public WorkFlowState GetCurrentState() { return WorkFlowState.Manager; } public ActivityState GetActivityState() { return ActivityState.Approve | ActivityState.Reject | ActivityState.Read; } } } |
再创建RefuseState class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | /******************************************************************************** ** Class Name: RefuseState ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: RefuseState class *********************************************************************************/ namespace WorkFlowService.DAL { using WorkFlowCommon; using IDAL; public class RefuseState : IStateBase { public WorkFlowState Execute(ActivityState activityState) { return WorkFlowState.Refuse; } public WorkFlowState GetCurrentState() { return WorkFlowState.Refuse; } public ActivityState GetActivityState() { return ActivityState.Read; } } } |
再创建StateMapping class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | /******************************************************************************** ** Class Name: StateMapping ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: StateMapping class *********************************************************************************/ namespace WorkFlowService.Help { using System.Collections.Generic; using DAL; using IDAL; public class StateMapping { public List<IStateBase> StateBasesList; private StateMapping() { Init(); } private static StateMapping _instance; public static StateMapping Instance { get { if (_instance == null ) _instance = new StateMapping(); return _instance; } } private void Init() { StateBasesList = new List<IStateBase> { new CommonState(), new ManageState(), new DoneState(), new RefuseState() }; } } } |
再创建WorkFlowEngine class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /******************************************************************************** ** Class Name: WorkFlowEngine ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: WorkFlowEngine class *********************************************************************************/ namespace WorkFlowService.BLL { using WorkFlowCommon; using DAL; using Help; using IDAL; public class WorkFlowEngine { private IStateBase GetCurrentWorkFlowStateByWorkFlowState(WorkFlowState workFlowState) { foreach ( var iStateBase in StateMapping.Instance.StateBasesList) { if (iStateBase.GetCurrentState() == workFlowState) return iStateBase; } return new CommonState(); } public WorkFlowState Execute(WorkFlowState workFlowState,ActivityState activityState) { return GetCurrentWorkFlowStateByWorkFlowState(workFlowState).Execute(activityState); } public ActivityState GetActivityStateByWorkFlowState(WorkFlowState workFlowState) { return GetCurrentWorkFlowStateByWorkFlowState(workFlowState).GetActivityState(); } } } |
最后创建Nunit Test
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | /******************************************************************************** ** Class Name: TestStateWorkFlowTest ** Author: spring yang ** Create date: 2013-3-13 ** Modify: spring yang ** Modify Date: 2012-3-13 ** Summary: TestStateWorkFlowTest interface *********************************************************************************/ namespace TestCommunication.WorkflowService { using Common; using NUnit.Framework; using WFService; public class TestStateWorkFlowTest : BaseActivity { private WorkFlowServiceClient WfServiceInstance { get { return new WorkFlowServiceClient(); } } [Test] public void TestNewWorkflow() { var appEntity = new AppInfoModel { ActivityState = ActivityState.Submit.ToString(), AppId = "001" , WorkflowName = "TestStateWorkFlow" , UserId = "001" , CurrentState = "Common" }; var result = WfServiceInstance.NewWorkFlow(appEntity); Assert.AreEqual(result, "Manage" ); } [Test] public void TestManageApproveWorkflow() { var appEntity = new AppInfoModel { ActivityState = ActivityState.Submit.ToString(), AppId = "002" , WorkflowName = "TestStateWorkFlow" , UserId = "002" , CurrentState = "Common" }; var result = WfServiceInstance.NewWorkFlow(appEntity); Assert.AreEqual(result, "Manage" ); var manageEntity = new AppInfoModel { ActivityState = ActivityState.Approve.ToString(), AppId = "002" , WorkflowName = "TestStateWorkFlow" , UserId = "003" , CurrentState = "Manage" }; var manageResult = WfServiceInstance.Execute(manageEntity); Assert.AreEqual(manageResult, "Done" ); } [Test] public void TestManageRejectWorkFlow() { var appEntity = new AppInfoModel { ActivityState = ActivityState.Submit.ToString(), AppId = "004" , WorkflowName = "TestStateWorkFlow" , UserId = "004" , CurrentState = "Common" }; var result = WfServiceInstance.NewWorkFlow(appEntity); Assert.AreEqual(result, "Manage" ); var manageEntity = new AppInfoModel { ActivityState = ActivityState.Reject.ToString(), AppId = "004" , WorkflowName = "TestStateWorkFlow" , UserId = "005" , CurrentState = "Manage" }; var manageResult = WfServiceInstance.Execute(manageEntity); Assert.AreEqual(manageResult, "Refuse" ); } [Test] public void TestSaveWorkflow() { var appEntity = new AppInfoModel { ActivityState = ActivityState.Save.ToString(), AppId = "006" , WorkflowName = "TestStateWorkFlow" , UserId = "006" , CurrentState = "Common" }; var result = WfServiceInstance.NewWorkFlow(appEntity); Assert.AreEqual(result, "Common" ); } [Test] public void TestRevokeWorkflow() { var appEntity = new AppInfoModel { ActivityState = ActivityState.Submit.ToString(), AppId = "007" , WorkflowName = "TestStateWorkFlow" , UserId = "007" , CurrentState = "Common" }; var result = WfServiceInstance.NewWorkFlow(appEntity); Assert.AreEqual(result, "Manage" ); var commonEntity = new AppInfoModel { ActivityState = ActivityState.Revoke.ToString(), AppId = "007" , WorkflowName = "TestStateWorkFlow" , UserId = "007" , CurrentState = "Common" }; var revokeResult = WfServiceInstance.Execute(commonEntity); Assert.AreEqual(revokeResult, "Common" ); } [Test] public void TestResubmitWorkflow() { var appEntity = new AppInfoModel { ActivityState = ActivityState.Submit.ToString(), AppId = "007" , WorkflowName = "TestStateWorkFlow" , UserId = "007" , CurrentState = "Common" }; var result = WfServiceInstance.NewWorkFlow(appEntity); Assert.AreEqual(result, "Manage" ); var commonEntity = new AppInfoModel { ActivityState = ActivityState.Revoke.ToString(), AppId = "007" , WorkflowName = "TestStateWorkFlow" , UserId = "007" , CurrentState = "Common" }; var revokeResult = WfServiceInstance.Execute(commonEntity); Assert.AreEqual(revokeResult, "Common" ); var resubmitEntity = new AppInfoModel { ActivityState = ActivityState.Resubmit.ToString(), AppId = "007" , WorkflowName = "TestStateWorkFlow" , UserId = "007" , CurrentState = "Common" }; var lastResult = WfServiceInstance.Execute(resubmitEntity); Assert.AreEqual(lastResult, "Manage" ); } } } |
查看运行的结果:
欢迎各位参与讨论,如果觉得对你有帮助,请点击 推荐下,万分谢谢.
作者:spring yang
出处:http://www.cnblogs.com/springyangwc/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!