精华帖 (2) :: 良好帖 (16) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-07-30
工作流的种类: 1、侧重人机交互的工作流,以WFMC规范为重点参考; 2、侧重服务整合和应用自动化的工作流,以BPEL规范为重点参考。 无论哪种,陷进去都是一个坑。我关注前者,研究思路和方法: 1、了解规范:看WFMC的资料,了解5个接口模型,了解XPDL; 2、了解开源产品:研究OSWorkflow(这个我花了些力气,也在整理学习笔记)、Shark、OBE; 3、适度看看当前强大的商用工作流,以ULTIMUS为重点。 研究了几天,总觉得应该工作流应该基于Event-Driven FSM才是引擎的微内核,也更贴近WFMC所描述的概念与状态模型,而Petri Nets总觉得有点怪怪的。 于是又google翻这些资料,得看大师的文章: http://en.wikipedia.org/wiki/Finite_state_machine http://en.wikipedia.org/wiki/Event_driven_finite_state_machine …… 也找到了一些java FSM的实现,但还没深入研究。 这时候我想试问一下了:工作流是否应该建立在有限状态机(Finite State Machine, FSM)引擎之上? 还希望大家切磋、指导。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-07-30
这是jfsm提供的使用FSM来做计算器的demo,代码很强很简洁
package org.jfsm.demo.calculator; import org.jfsm.core.FSMException; import org.jfsm.core.FSMInput; import org.jfsm.core.FSMOutput; import org.jfsm.core.RetSignal; import org.jfsm.core.SimpleFSM; import org.jfsm.core.SimpleFSMContext; class CalcController { static public class CalcContext extends SimpleFSMContext { int num1, display; char op; void calculate() { switch (op) { case '+': num1 += display; break; case '-': num1 -= display; break; case '*': num1 *= display; break; case '/': num1 /= display; break; default: } display = num1; } @Override public String toString() { return "( num1:" + num1 + ", display:" + display + ", op:" + op + " )"; } } static public class CalcInputs extends FSMInput<CalcContext> { SignalM<Character> key, digit, op; Signal backspace, equals; }; private enum State { Init, Num1, Op, Num2 } static class CalcFSM extends SimpleFSM<CalcContext, CalcInputs, FSMOutput> { @Override protected void build(TransitionMap tm) { tm.setInitialState(State.Init); tm.putDefault(in.key, null, mhKey); tm.put(State.Init, in.digit, State.Num1, mhFirstDigit); tm.put(State.Init, in.backspace, State.Init, ehClear); tm.put(State.Init, in.op, State.Op, mhOp); tm.put(State.Init, in.equals, State.Init, null); tm.put(State.Num1, in.digit, State.Num1, mhNumAppend); tm.put(State.Num1, in.backspace, State.Num1, ehNumBack); tm.put(State.Num1, in.op, State.Op, mhOp); tm.put(State.Num1, in.equals, State.Init, null); tm.put(State.Op, in.digit, State.Num2, mhFirstDigit); tm.put(State.Op, in.backspace, State.Op, ehClear); tm.put(State.Op, in.op, State.Op, mhOp); tm.put(State.Op, in.equals, State.Init, ehEquals); tm.put(State.Num2, in.digit, State.Num2, mhNumAppend); tm.put(State.Num2, in.backspace, State.Op, ehNumBack); tm.put(State.Num2, in.op, State.Op, mhOpOnNum2); tm.put(State.Num2, in.equals, State.Init, ehEquals); } MH<Character> mhKey = new MH<Character>() { public RetSignal handle(CalcContext context, Character key) { if (key >= '0' && key <= '9') { return in.digit.asNextSignal(key); } else if (key == '+' || key == '-' || key == '*' || key == '/') { return in.op.asNextSignal(key); } else if (key == '=') return in.equals; else if (key == 'D') return in.backspace; else return null; } }; EH ehClear = new EH() { public RetSignal handle(CalcContext ctx) { ctx.display = 0; return null; } }; MH<Character> mhFirstDigit = new MH<Character>() { public RetSignal handle(CalcContext ctx, Character key) { ctx.display = 0; return in.digit.asNextSignal(key); } }; MH<Character> mhNumAppend = new MH<Character>() { public RetSignal handle(CalcContext ctx, Character key) { ctx.display = ctx.display * 10 + (key - '0'); return null; } }; EH ehNumBack = new EH() { public RetSignal handle(CalcContext ctx) { ctx.display /= 10; return null; } }; MH<Character> mhOp = new MH<Character>() { public RetSignal handle(CalcContext ctx, Character key) { ctx.op = key; ctx.num1 = ctx.display; return null; } }; MH<Character> mhOpOnNum2 = new MH<Character>() { public RetSignal handle(CalcContext ctx, Character key) { ctx.calculate(); ctx.op = key; return null; } }; EH ehEquals = new EH() { public RetSignal handle(CalcContext ctx) { ctx.calculate(); return null; } }; } CalcInputs dispatcher; CalcContext ctx; public CalcController() throws FSMException { dispatcher = new CalcFSM().createInstance().getInput(); ctx = dispatcher.newContext(); } } |
|
返回顶楼 | |
发表时间:2009-07-30
如果我没弄错,工作流引擎就是个有限状态机:)
不知道实现起来是否会遇到麻烦,支持这个做法! |
|
返回顶楼 | |
发表时间:2009-07-30
没看到过比较“纯粹”使用FSM的工作流产品,我现在也拿捏不准:如果基于FSM来架构,会是什么样子,会不会遇到难以逾越的困难?
看来又得战死很多脑细胞:) |
|
返回顶楼 | |
发表时间:2009-07-31
做了两年的工作流开发得出的一个结论,当前的工作流产品还不如一个简单的有效状态机,代码简单直观。
|
|
返回顶楼 | |
发表时间:2009-07-31
之前我们的工作流也在维护状态,做transition,但更多时候状态只是一个属性,改变了属性后,通过持久化的此属性进行检索什么的,说难听的,我一直称之为工具,不叫引擎。
现在看了workflow patterns,看了FSM/Petri Net,才真是有点感觉,现在的关键是论证,持续的论证 |
|
返回顶楼 | |
发表时间:2009-08-04
FSM的组件模型:
说明: 1、核心包括State、Transition、Condition、Action等对象,复杂对象(如基于事件的TriggerCondition)可基于这些基对象进行扩展、变化; 2、Transition通过fromState(source)及toState(target)进行状态的变迁,可能会触发Action; 3、State的类型包括initialState、normalState、terminationState三种。 工作项的StateModel: 下一步关注的重点:FSM适用的具体场景 |
|
返回顶楼 | |
发表时间:2009-08-04
不错,其实工作流就应该是这个样子的。
State为什么还要分3种,没有这个必要把,就是一个单纯的状态,或者可以理解为传统工作引擎的节点 还有就是Transition我觉得fromState(source)就可以了,好像没有必要搞toState(target)吧。 |
|
返回顶楼 | |
发表时间:2009-08-05
最后修改:2009-08-05
rain2005 写道 不错,其实工作流就应该是这个样子的。
State为什么还要分3种,没有这个必要把,就是一个单纯的状态,或者可以理解为传统工作引擎的节点 还有就是Transition我觉得fromState(source)就可以了,好像没有必要搞toState(target)吧。 过程状态可以很多(比如很多次审批,但流程还在运行),但起始状态只能是一种(比如命名为“new”或者就是“initial”,类型为initial),而结束状态可以有多种(比如命名为“canclled”或“finished”或“aborted”,类型为terminationState) 但从类型来说,总体就是三种——我的观点 另外,Transition务必是从哪儿到哪儿,肯定得有去处。当然了,这种去处可能是一种JOIN,或者是自动活动(比如自动发邮件),但总归有去处,否则路就断了。 |
|
返回顶楼 | |
发表时间:2009-08-05
楼主的思路也是不错的一种,可以参考jbpm4.0啊,它采用PVM来设计的,个人认为是一个更power的FSM。
|
|
返回顶楼 | |