首页 > 编程开发 > Objective-C编程 >
-
WF从入门到精通之基于状态的工作流
学习完本章,你将掌握:
1.理解状态机的概念以及它怎样被模拟到工作流处理中的
2.创建基于状态的工作流
3.运用初始(initial)和终止(terminal)状态条件
4.使用代码进行状态的切换
在第四章“活动和工作流类型介绍”中,我阐述过你使用WF所能创建的工作流类型,在那里我提到过基于状态的工作流。基于状态的工作流模型被认为是有限自动机(finite state machine)。基于状态的工作流在工作流需要和外部事件进行许多交互的场合中大出风头。在事件触发并被工作流处理的时候,工作流能按要求进行状态的切换。
WF为创建基于状态的工作流提供了富余的开发体验,你迄今为止在本书中看到的许多东西都适用于基于状态的工作流。例如,当一个状态切换过来的时候,假如你想的话,你能去执行几个顺序活动,进行条件判定(使用规则或者代码),或者使用一个迭代活动结构来循环访问一些数据点。唯一真正的区别是活动怎样排队执行。在顺序或并行工作流中,它们以出现的顺序进行排队。但是在基于状态的工作流中,活动以状态切换进出来进行排队。事件通常驱动这些切换过程,但是这条规则不是通用的。让我们再看看状态机的概念并把这些概念和你能使用的WF活动结合起来去构建你的工作流。
状态机的概念
状态机的目的是构建你业务流程中的离散点,切换通过事件来控制。例如,把你的洗衣机接通电源,然后关门并按下启动按钮。按下启动按钮时初始化了一个状态机,它通过运行各种各样的清洁周期来清洗你待洗的衣物直到这些周期全部完成。
状态机有一个已知的起点和一个已知的终点。中间的状态应能通过预期事件的触发去进行控制,但机器总处于一个特定的状态。有时事件把状态机扔进无效的状态中,这种情形和在你的应用程序中维持未处理的异常的情形来说并没有什么不同,整个过程不是忽然停止就是完全崩溃。无论哪种情况,切换到无效状态都是要密切监视的,至少在数字电子系统(digital electronic systems)中是这样。
编缉推荐阅读以下文章
- WF4.0 Beta1之旅(6):自定义活动
- WF4.0 Beta1之旅(5):规则引擎的变化
- WF 4.0的建模风格:顺序和Flowchart
- WF 4.0 beta1中的跟踪机制
- WF4.0 Beta1之旅(4):Bookmark的使用
- WF 4.0 beta1活动概览(1):Procedural
- WF4.0 Beta1之旅(3):全新的FlowChart
- WF4.0 Beta1之旅(2):异常处理
- WF4.0 Beta1之旅(1):基本介绍
- 初窥WF 4.0 beta1
总的来说,第4章涵盖了涉及状态机的基本概念。可看看“状态活动”这一节快速复习一下。让我们从怎样设计活动转到在基于状态的工作流中怎样使用活动去吧。
使用状态活动
也许你不会太惊讶,在你的基于状态的工作流中State活动构建了一个状态。它是一个组合活动,但它局限于只接受特定类型的活动来作为它的子活动,它们是:EventDriven活动,StateInitialization活动,StateFinalization活动以及其它State活动。EventDriven活动等待(监听)那些将导致切换到另一个状态的事件,而在状态被切换进来和切换出去的时候,StateInitialization和StateFinalization是保证能分别去执行相应处理的活动。对于能拖拽第二个State活动到一个已存在的State活动中去可能看起来有些古怪,但其意图是提供一种在父状态机中嵌入子状态机的能力。
对于你的状态能容纳的那些有效活动的数目也有一个限制。只允许有唯一的一个StateInitialization和StateFinalization,你可以只有其中的一个,但每一个都不能超过一个。它们都不是必须的。
但是并没有说你不能只有一个或者更多的子EventDriven和State活动。事实上,一般都能找到多个EventDriven活动,因为每一个事件可能会导致切换到一个不同的状态。例如,一个“不批准(disapprove)”事件可能会切换到最终的状态(结束状态),而一个“批准(approve)”事件则可能切换到一个预定的状态并要求进行更多的审批。至于State活动,假如你要创建嵌入的基于状态的工作流的话,毫无疑问超过一个也应当是允许的。只有一个状态(切换)的基于状态的工作流构建成了一个简单的顺序工作流,因此在那种情况下你应当直接使用一个顺序工作流。在任何情况下,使用State活动只需从工具箱中拖拽它的一个实例到工作流视图设计器上,唯一的必要条件是工作流自身必须是基于状态的工作流而不是顺序工作流。然后确定你的状态活动应容纳些什么子活动,并按需要把它们拖拽进去,牢记你只能插入四种类型的活动。
使用SetState活动
假如你回忆一下我在第四章中介绍过的状态机示例的话,下图14-1将看起来很眼熟。确实,它是一个(被简化了的)自动售货机状态图。我认为把这样一个状态图制成一个真实的基于状态的WF工作流并使用一个用户界面来驱动它会是很有趣的一件事,考虑到我缺少艺术细胞,该用户界面会被构成成一个简陋的不含酒精饮料(“汽水”)的自动售货机。
图14-1饮料机的状态图
考虑到没有用户互动,该饮料售货机应用程序的界面如图14-2所示。一瓶饮料的价格是$1.25。当你投入硬币的时候,左边的饮料图形按钮都处于非激活状态。但是,当你投入了足够的金额后,这些饮料按钮就能使用并且你可以做出选择。这个简化的模型不会处理如退款和更改之类的事情,但如果你愿意的话,你可随意修改该应用程序。
备注:为简便起见,我并没有使该示例应用程序国际化。它模拟的是只接受美国货币的自动售货机。但是,请记住这里的重点是工作流,而不是所使用的货币单位。
图14-2饮料机处于初始状态时的用户界面
但是,你不能真正把硬币投到一个Windows Forms应用程序中,因此我提供了5¢,10¢和25¢三个按钮(注:符号¢代表美分)。很抱歉,只有这几种硬币。当你首次点击其中一个硬币按钮的时候,一个新的基于状态的工作流实例就被启动了,执行该工作流的状态图如图14-1所示。图14-3为你展示了饮料机在投入了几个硬币后的情况。基于状态的工作流随时跟踪接收到的硬币并把金额总计反馈给应用程序,该应用程序在一个模拟的液晶二极管显示屏上把它显示出来。
图14-3投入了硬币的饮料机用户界面
当投入了足够的硬币时,工作流就通知应用程序现在用户可以选择饮料了,如图14-4所示。应用程序让位于用户界面左边的各个饮料按钮处于可用状态(enable)。
图14-4允许选择饮料的饮料机用户界面
当点击了左边的某个饮料按钮后,即如图14-4中显示的变黑的按钮,一个标签(label)将呈现出来并显示“Soda!”,这是我模拟一瓶客户选中的饮料从机器中落出的一种方式。为重置整个过程,可点击“Reset”按钮。这不会影响到该工作流但是会重置用户界面上的按钮。图14-2显示了这种情形的用户界面,你可再一次启动所有的处理过程。
图14-5选中了某瓶饮料后的饮料机用户界面
已经为你创建了大量的应用程序代码。假如你读完该SodaMachine示例的代码,你将发现我使用了CallExternalMethod活动(看看第8章中的“工作流数据传送”)以及HandleExternalEvent活动(看看第10章“事件活动”)。有大量的工具来为你的工作流和你的应用程序之间进行交互。剩下的工作就是创建该工作流自身,下面就是具体的做法。
创建一个基于状态的工作流
1.该SodaMachine应用程序再次为你提供了两个版本:完整版本和非完整版本。你需要下载本章源代码,打开SodaMachine文件夹中的解决方案。
2.当SodaMachine解决方案在Visual Studio中打开后,从Visual Studio的“生成”菜单中选择“生成解决方案”。解决方案中的项目包含各种各样的依赖,编译该解决方案生成了那些关联的项目所能引用的程序集。
3.在Visual Studio的解决方案资源管理器窗口中找到SodaFlow项目中的Workflow1.cs文件。然后在工作流视图设计器中打开该工作流准备编辑。
备注:我已经创建了这个基本的工作流项目,因为该应用使用的CallExternalMethod和HandleExternalEvent活动的相关技术你在第8章和第10章中已经看过。重复这些必须的步骤来创建这些常规活动没有任何必要,但是假如你从头开始创建工作流项目的话,你需要去做这些工作。
使用状态活动
也许你不会太惊讶,在你的基于状态的工作流中State活动构建了一个状态。它是一个组合活动,但它局限于只接受特定类型的活动来作为它的子活动,它们是:EventDriven活动,StateInitialization活动,StateFinalization活动以及其它State活动。EventDriven活动等待(监听)那些将导致切换到另一个状态的事件,而在状态被切换进来和切换出去的时候,StateInitialization和StateFinalization是保证能分别去执行相应处理的活动。对于能拖拽第二个State活动到一个已存在的State活动中去可能看起来有些古怪,但其意图是提供一种在父状态机中嵌入子状态机的能力。
对于你的状态能容纳的那些有效活动的数目也有一个限制。只允许有唯一的一个StateInitialization和StateFinalization,你可以只有其中的一个,但每一个都不能超过一个。它们都不是必须的。
但是并没有说你不能只有一个或者更多的子EventDriven和State活动。事实上,一般都能找到多个EventDriven活动,因为每一个事件可能会导致切换到一个不同的状态。例如,一个“不批准(disapprove)”事件可能会切换到最终的状态(结束状态),而一个“批准(approve)”事件则可能切换到一个预定的状态并要求进行更多的审批。至于State活动,假如你要创建嵌入的基于状态的工作流的话,毫无疑问超过一个也应当是允许的。只有一个状态(切换)的基于状态的工作流构建成了一个简单的顺序工作流,因此在那种情况下你应当直接使用一个顺序工作流。在任何情况下,使用State活动只需从工具箱中拖拽它的一个实例到工作流视图设计器上,唯一的必要条件是工作流自身必须是基于状态的工作流而不是顺序工作流。然后确定你的状态活动应容纳些什么子活动,并按需要把它们拖拽进去,牢记你只能插入四种类型的活动。