这个模式我们组用的很多,基本不需要怎么讲解了,这里就随便举个例子说说
就举经典的地铁投币门吧。如果原来锁着,想通过就要想警报,而投币就会解锁;如果原来开着,那么投币就会向你道谢,通过后重新上锁。
如果设计程序来模仿这个门,那么很简单的使用if/else或者switch/case就可以搞定:
if(state==locked)
if(event==coin)
unlock()
state=unlocked
else if(event==pass)
alert()
else if(state==unlocked)
if(event==coin)
thanks()
else if(event==pass)
lock()
state=locked
这个实现的缺点我就不多说了,很难对未来的扩展做出好的响应,逻辑集中,容易出错。
不用这个,我们还可以把 状态/事件/动作/动作后的状态 写成一个状态迁移表
transitions = Array of transition
transitions.Add(locked, coin, unlock, unlocked)
transitions.Add(locked, pass, alert, locked)
transitions.Add(unlocked, coin, thanks, unlocked)
transitions.Add(unlocked, pass, lock, locked)
函数中调用
for(i=0; i<transitions.size(); i++)
{
transition = transitions.at(i);
if(state==transition.state && event==transition.event)
{
transition.action.execute()
state=transition.newstate
}
}
这个其实不错,每次修改时,只要维护好迁移表就可以了,代价是速度,遍历表的速度,还有如果状态很多时,很烦人的维护工作。
就举经典的地铁投币门吧。如果原来锁着,想通过就要想警报,而投币就会解锁;如果原来开着,那么投币就会向你道谢,通过后重新上锁。
如果设计程序来模仿这个门,那么很简单的使用if/else或者switch/case就可以搞定:
if(state==locked)
if(event==coin)
unlock()
state=unlocked
else if(event==pass)
alert()
else if(state==unlocked)
if(event==coin)
thanks()
else if(event==pass)
lock()
state=locked
这个实现的缺点我就不多说了,很难对未来的扩展做出好的响应,逻辑集中,容易出错。
不用这个,我们还可以把 状态/事件/动作/动作后的状态 写成一个状态迁移表
transitions = Array of transition
transitions.Add(locked, coin, unlock, unlocked)
transitions.Add(locked, pass, alert, locked)
transitions.Add(unlocked, coin, thanks, unlocked)
transitions.Add(unlocked, pass, lock, locked)
函数中调用
for(i=0; i<transitions.size(); i++)
{
transition = transitions.at(i);
if(state==transition.state && event==transition.event)
{
transition.action.execute()
state=transition.newstate
}
}
这个其实不错,每次修改时,只要维护好迁移表就可以了,代价是速度,遍历表的速度,还有如果状态很多时,很烦人的维护工作。