我的顶级状态机有一些状态和边缘。我将把这称为父状态机。
A ----> B ----> C父状态机中的任何状态也可以是状态机。我给这些孩子打电话叫国家机器。
___________
/ \
A ----> | B0->B1->B2 | ----> C
\____________/如果父状态机从A转换到B,则B的状态机接管。一旦B完成运行,它应该如何将控制放弃给父状态机并转换到状态C?你使用哪种设计模式?
如果您想知道,我在父状态机中有子状态机,因为我的确切项目非常复杂,很自然地封装子状态的内部工作。
发布于 2012-02-09 20:07:17
每个状态机都有某种事件处理程序和触发这些事件的方法。该处理程序将现有状态和事件类型作为输入,选择新状态,并可选择运行一些副作用代码。
本质上,在状态B中,您的主事件处理程序将不识别的任何事件转发给B的S事件处理程序,并保持在状态B中。当B希望转换到C时,它会将适当的事件发布到主事件处理程序。
发布于 2012-02-09 19:51:13
你读过Taoup的这段吗?完成此任务有几种不同的方法,但其中许多方法取决于您如何拆分状态机。它们是分开的过程吗?线?物品?
找出你是如何构建它们的,看看它们是否有一种规范的沟通方式。如果一个系统不存在,那么您的系统设计可能是错误的。
对我来说,我会观察不同的过程,把stdin和stdout连接在一起。子状态机然后变得独立,在stdin上操作,在stdout上输出。它成为父状态机的工作,启动子进程,连接管道,然后转储数据并等待结果。所有这些事情都是用现代语言做的,所以应该很容易做到。
发布于 2012-02-09 20:31:18
分离这两台状态机并使用它们之间的消息传递。因此,状态机1将从A B C开始,在B状态下它检查状态机2的当前结果。如果输出已经改变,那么状态机1可以解释它,状态机2不需要知道状态机1实际上是如何工作的。类似于:
typedef struct StateMachine {
void(*Update)(); // function to update the state machine
int Data; // generic temp holder to survive state contexts
int State; // current state of our state machine
int *Message; // pointer to a shared integer for message passing
};
int main(void) {
int Message = 0;
/* NewStateMachine would malloc the struct, pass in the int reference
* and function pointer as well as add it to a circularly linked list */
NewStateMachine(&Message, MainLoop);
NewStateMachine(&Message, MinorLoop);
StateMachine *Current = StateMachine_CLL.First;
for(;;) {
Current->Update(Current); /* Update the current state machine */
Current = Current->Next; /* And the advance to the next one */
}
}
void MainLoop(StateMachine *this) {
switch(this.State) {
case 0:
CloseCoolantTank(1); /* safe to call if valve already closed */
CloseCoolantTank(2); /* safe to call if valve already closed */
this.State = 1;
break;
case 1:
/* we have a message, do something */
if(*this.Message) this.State = 2;
/* otherwise stall at this state until we get a message */
else this.State = 1;
break;
case 2:
if(*this.Message == 1) this.State = 3; /* warm */
else if(*this.Message == 2) this.State = 4; /* hot! */
else this.State = 0; /* cooled down, shut off valves */
this.Message = 0; /* clear the message */
break;
case 3:
OpenCoolantTank(1); /* opens the valve, safe to call if already open */
this.State = 2; /* recheck for new message */
break;
case 4:
OpenCoolantTank(2); /* opens the valve, safe to call if already open */
this.State = 3; /* also open coolant tank 1 for extra cooling */
break;
}
}
/* Monitor temperature and send messages on overheat */
void MinorLoop(StateMachine *this) {
switch(this.State) {
case 0:
this.Data = ReadADCValue();
this.State = 1;
break;
case 1:
if(this.Data > 150) *this.Message = 2;
else if(this.Data > 100) *this.Message = 1;
this.State = 0;
break;
}
}https://softwareengineering.stackexchange.com/questions/134252
复制相似问题