我对如何实现我的状态机感到有点困惑 我已经知道它是等级的,因为一些州分享相同的行动 我通过这些参数确定了我需要做什么:
我的层次结构由Class确定, OpCode 表示操作 派生可以使用 Base 的操作码,特定可以使用 OpCodes em> Base 和 Derived 天真的实现如下:
void (*const state_table [MAX_CLASSES][MAX_OPCODES]) (state *) {
{base_state1, base_state2, NULL, NULL},
{base_state1, base_state2, derived_state1, NULL},
{base_state1,base_state2, derived_state1, specific_state3},
};
void dispatch(state *s)
{
if (state_table[s->Class][s->OpCode] != NULL)
state_table[s->Class][s->OpCode](s);
}
这将很快变得无法维持 是否有另一种方法将状态映射到超类?
编辑:
进一步的计算让我觉得我可能会使用最多(如果不是全部) OpCodes ,但我不会使用所有可用的 Classes 。
另一个澄清:
某些操作码可能会通过多个派生和基本类共享。
例如:
我调用了另一个 Class MyGroup ,这是派生类。它有 OpCodes : STATE_FLIP , STATE_FLOP 。
第三个类是特定 类名为 ThingInMyGroup 有 OpCode : 的 STATE_FLIP_FLOP_AND_FLOOP
因此,从服务器发送一个类任何的消息,在所有客户端中收到并处理。
从服务器发送包含 MyGroup 类的邮件,在所有客户端中收到并仅在属于 MyGroup 的客户端上处理,任何 OpCodes 对任何类有效的 MyGroup 类有效。
从服务器发送包含 ThingInMyGroup 类的邮件,在所有客户端中收到并仅在属于 MyGroup 的客户端上处理,并且是 ThingInMyGroup *,对任何类和 MyGroup 类有效的任何** OpCodes 对 ThingInMyGroup 类有效。
收到消息后,客户端将相应地发出ACK / NACK。
我不喜欢使用switch case或const数组,因为当它们变大时它们将变得不可维护 我需要一个灵活的设计,允许我:
答案 0 :(得分:4)
有几种方法可以解决这个问题。这是一个:
typedef unsigned op_code_type;
typedef void (*dispatch_type)(op_code_type);
typedef struct hierarchy_stack hierarchy_stack;
struct hierarchy_stack {
dispatch_type func;
hierarchy_stack *tail;
};
void dispatch(state *s, hierarchy_stack *stk) {
if (!stk) {
printf("this shouldn't have happened");
} else {
stk->func(s, stk->tail);
}
}
void Base(state *s, hierarchy_stack *stk ) {
switch (s->OpCode) {
case bstate1:
base_state1(s);
break;
case bstate2:
base_state(2);
break;
default:
dispatch(s, stk);
}
}
void Derived(state *s, hierarchy_stack *stk ) {
switch(s->opcode) {
case dstate1:
deriveds_state1(s);
break;
default:
dispatch(s, stk);
}
}
...
这样可以很好地本地化你的“类”,这样如果你确定Derived需要100多个方法/操作码,那么你只需要编辑用于定义操作码的方法和枚举(或其他)。
处理这个问题的另一种更动态的方法是在每个“类”中都有一个指向“类”的父指针,它会处理它无法处理的任何东西。
2D表方法快速而灵活(对于操作码0,Derived可能具有与Base不同的处理程序),但它会快速增长。
答案 1 :(得分:1)
我编写了一个小工具,可以生成类似于基于迷你语言的幼稚实现的代码。语言刚刚指定了状态操作码 - 操作关系,所有操作都只是符合typedef的C函数。
它没有处理HSM方面,但这可以相对容易地添加到语言中。
我建议采用这种方法 - 创建一种语言,为您提供一种描述状态机的简洁方法,然后根据该机器描述生成代码。这样,当你需要从现在开始一个月后插入一个新状态时,整个事情并不是一个混乱的编辑。
如果您需要代码,请告诉我,我会确保它仍然可以在某个地方使用。