状态模式:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
需求
上午状态好,中午想睡觉,下午渐恢复,加班苦煎熬。其实是一种状态的变化,不同的时间,会有不同的状态。你现在用代码来实现一下。
需求分析
- 状态可能修改、增加、删除
- 状态转移条件可能变化:该例中即时间
代码
状态处理
c
typedef enum {
MINSTATE,
FORENOON,
NOON,
AFTERNOON,
EVENING,
SLEEPING,
REST,
MAXSTATE
} State;
typedef struct StateMove {
State prev;
State next;
float hour;
void (*handle)(struct StateMove *, struct StateMove *, char **words, float);
} StateMove;
void MoveHandle(StateMove *start, StateMove *obj, char **words, float workTime) {
if(workTime < obj->hour) {
printf("当前时间:%f点 %s\n", workTime, words[obj->prev]);
}
else {
// 现在每一个状态只对应一个动作
start[obj->prev].handle(start, &(start[obj->next]), words, workTime);
}
}
客户端
支持修改点:1.状态打印 2.下一级动作和时间条件

注意不要修改后不要让状态死循环
c
void PrintState(StateMove *move, char **words, float time) {
move[0].handle(move, move, words, time);
}
int main() {
// 状态
char *words[] = {
"上班前",
"上午工作,精神百倍",
"饿了,午饭,犯困,午休",
"下午状态还不错,继续努力",
"加班哦,疲累之极",
"不行了,睡着了",
"下班了"
};
// 状态转移
StateMove move[] = {
{MINSTATE, FORENOON, 9, MoveHandle},
{FORENOON, NOON, 12, MoveHandle},
{NOON, AFTERNOON, 13, MoveHandle},
{AFTERNOON, EVENING, 17, MoveHandle},
{EVENING, SLEEPING, 20, MoveHandle},
{SLEEPING, REST, 22, MoveHandle}
};
float time;
printf("请输入工作时间:\n");
scanf("%f", &time);
PrintState(move, words, time);
return 0;
}
UML图

总结
- 状态模式使用场景?
"状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,那就没必要用'状态模式'了。"