好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

大败笔,状态机

大败笔,状态机

在做网站的时候,忘了使用state_machine,这个东东,要不然在订单状态流转这一块可以省得自己造轮子了,大败笔,

但是我估计一般的网站也没用上这么高端的东西,原谅自己吧,哈哈,下次找机会用用

微软的状态机的例子

http://msdn.microsoft.com/zh-cn/library/ms741709(VS.90).aspx

应该 是使用的wcf

2010年4月9日

强大的有限状态机 - state_machine

在推荐Ruby on Rails给做企业应用的朋友时候,比较常见的问题有"Ruby有没有好用的开源工作流引擎?",基于有限状态机( Finite State Machine - FSM )构建工作流引擎是经常使用的实现方法,写篇短文介绍一下Ruby世界里的有限状态机: 

首先列几个开源的Ruby FSM项目: 
state_machine act_as_state_machine Ryan Allen's workflow Alter Ego
其中第一个项目state_machine是作者经过 2年半时间 陆续开发的,特性比较完整,而且最近开发也比较活跃,下面简单介绍一下它的强大功能: 
可以在任意的Ruby类里面定义多个状态机 基于属性的event transitions 提供了和ActiveRecord / DataMapper / Sequel等多个ORM的集成 提供了before/after transition hook以方便于集成 状态驱动的instance/class行为 基于GraphViz的创建状态机图片 ...

1. 基础用法:  
我们来看一下它提供的一个红绿灯的例子 


得益于Ruby语言的优秀特性,state_machine定义了一套简洁DSL,使得代码非常易懂/易维护: 

Ruby代码

class  TrafficLight      state_machine  :initial  =>  :stop   do   #定义初始状态为stop         event  :cycle   do   #定义cycle事件,让状态从stop到proceed到caution到stop进行改变           transition  :stop  =>  :proceed ,  :proceed  =>  :caution ,  :caution  =>  :stop         end       end      end   



使用这个红绿灯的代码: 

Ruby代码

light = TrafficLight. new    p light.state    6.times  do      light.cycle      p light.state      end   



2. transition hook:  
利用state_machine提供的before/after transition hook机制,我们可以简洁地实现很多需求,比如订单状态改变的时候,我们需要记录一下: 

Ruby代码

class  Order      state_machine  :initial  =>  :pending        before_transition  :log_state_change         #...        end          def  log_state_change(transition)        event, from, to = transition.event, transition.from_name, transition.to_name        puts( "Order #{number}: #{from} => #{to} on #{event}" )       end      end   



也可以有选择性地在某些关键状态改变时做些动作: 

Ruby代码

after_transition   :pending  =>  :completed ,  :pending  =>  :closed   do       #send email to order owner       end   



3. 和ORM集成:  
和Rails的ActiveRecord集成是很简单的一件事情,简单到你什么都不需要做,直接在Model文件里面定义就可以了: 

Ruby代码

class  Order < ActiveRecord::Base      state_machine  :initial  =>  :pending   do        event  :confirm   do         #...          end       end    end   



然后在数据库里面添加一个栏位叫state,这样就可以持久化了: 

Ruby代码

order = Order.create(...)    p order.state  # pending   



结合它默认设置的scope,我们就可以写出这样简洁而又符合自然语法的代码: 

Ruby代码

#找出所有状态为pending的订单,一一进行确认     Order.with_state( :pending ).all. each {|order| order.confirm}  



和DataMapper / Sequel集成也是很简单,都是直接在Model文件里面定义,然后数据库添加栏位,而不需要额外的工作。 

简单介绍到此,state_machine还有更多强大的功能不是这篇短文能够覆盖的,大家有兴趣的可以看它的文档和源代码。 

最后值得提一下的是,这个项目总共只有1200行不到的代码,和动辄超过万行的Java workflow engine相比,学习起来是很轻松愉快的。

posted @ 2010-04-09 17:02 玩玩乐乐 阅读(63) | 评论(0) |  编辑

查看更多关于大败笔,状态机的详细内容...

  阅读:42次