设计模式之状态模式20170712
行为型设计模式之状态模式:
一、含义
为每个状态创建与之对应的类(对应的每个类实现同一个接口或继承同一个抽象类,便于统一处理),并且再通过一个类切换状态
二、代码说明
1.一般包含三个角色抽象状态角色,具体状态角色,以及环境(上下文)角色(负责具体状态的切换)。
具体步骤:
1)定义环境角色,并初始化状态
2)通过环境角色执行行为,同时也就是对应状态的行为被执行
3)对应状态的行为的执行分为两种情况:
I、对应状态对应行为执行后,环境角色继续执行行为,调用的还是此状态,此状态的下一个行为(下一状态的行为)被执行,执行中会设置下一态(设置下一态一般都放在抽象父类中,同时由于是继承设置下一态时,也要把对应的环境对象设置进去(继承导致每个子类都有对应的环境类的引用),这样下一个状态对象才能调用环境类中的函数),设置完后再执行对应的下一个行为
II、或对应状态对应行为(函数)执行中,先执行对应的操作,然后设置下一态(显然也要把对应的环境对象设置进去),这样环境角色再次执行行为就是调用下一态的行为(函数)了,而不是还停留在本状态。
两种情况均可以,二选一即可,但是显然第二种方式更简单一点,但对外来看没有差异。
4)接下来再次调用环境角色执行行为,由于前面设置了状态,此时执行的就是下一状态的行为
5)不断调用环境角色执行行为,知道所有的状态行为执行完毕
6)扩展:不断调用环境角色执行行为可以使用建造者模式组装起来进行优化
2.在用C实现过程中也是参考这种思想,不过设置下一态不使用继承的方式,以电梯运行状态举例,状态迁移表如下:
具体实现如下:
1)状态模式使用场景:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : StatePatternUsage.c 5 * Description : 状态模式的使用 6 7 book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o StatePatternUsage RunningState.c StoppingState.c OpenningState.c ClosingState.c StatePattern.c StatePatternUsage.c 8 book@book-desktop:/work/projects/test/DesignPatterns$ ./StatePatternUsage 9 Lift door open! 10 Lift door close! 11 Lift door run! 12 Lift door stop! 13 14 * Created : 2017.07.12. 15 * Author : Yu Weifeng 16 * Function List : 17 * Last Modified : 18 * History : 19 ******************************************************************************/ 20 #include"stdio.h" 21 #include"malloc.h" 22 #include"stdlib.h" 23 #include"string.h" 24 #include"StatePattern.h" 25 26 27 28 29 /***************************************************************************** 30 -Fuction : main 31 -Description : 32 -Input : 33 -Output : 34 -Return : 35 * Modify Date Version Author Modification 36 * ----------------------------------------------- 37 * 2017/07/12 V1.0.0 Yu Weifeng Created 38 ******************************************************************************/ 39 int main(int argc,char **argv) 40 { 41 T_StateContext tStateContext=newStateContext; 42 T_State tState=newClosingState; 43 tStateContext.SetState(&tState); 44 45 tStateContext.Open(); 46 tStateContext.Close(); 47 tStateContext.Run(); 48 tStateContext.Stop(); 49 50 51 return 0; 52 }
隐藏(封装)了状态的变化过程,它的切换引起了行为的变化。对外来说,我们只看到行为的发生改变,而不用知道是状态变化引起的。
2)被调用者:
I、环境(上下文)角色(负责具体状态的切换):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : StatePattern.c 5 * Description : 状态模式 6 对各个状态进行管理,也可以改名为StateManage.c 7 为统一名称,本文件也是状态模式的核心故还是 8 命名为StatePattern.c 9 10 11 * Created : 2017.07.12. 12 * Author : Yu Weifeng 13 * Function List : 14 * Last Modified : 15 * History : 16 ******************************************************************************/ 17 #include"stdio.h" 18 #include"malloc.h" 19 #include"stdlib.h" 20 #include"string.h" 21 #include"StatePattern.h" 22 23 24 25 static T_State g_tState; 26 27 /***************************************************************************** 28 -Fuction : SetState 29 -Description : 公有函数 30 -Input : 31 -Output : 32 -Return : 33 * Modify Date Version Author Modification 34 * ----------------------------------------------- 35 * 2017/07/12 V1.0.0 Yu Weifeng Created 36 ******************************************************************************/ 37 void SetState(T_State *i_ptState) 38 { 39 memcpy(&g_tState,i_ptState,sizeof(T_State)); 40 } 41 42 /***************************************************************************** 43 -Fuction : SetState 44 -Description : 公有函数 45 -Input : 46 -Output : 47 -Return : 48 * Modify Date Version Author Modification 49 * ----------------------------------------------- 50 * 2017/07/12 V1.0.0 Yu Weifeng Created 51 ******************************************************************************/ 52 void GetState(T_State *o_ptState) 53 { 54 memcpy(o_ptState,&g_tState,sizeof(T_State)); 55 } 56 /***************************************************************************** 57 -Fuction : Open 58 -Description : 公有函数 59 -Input : 60 -Output : 61 -Return : 62 * Modify Date Version Author Modification 63 * ----------------------------------------------- 64 * 2017/07/12 V1.0.0 Yu Weifeng Created 65 ******************************************************************************/ 66 void Open() 67 { 68 g_tState.Open(); 69 } 70 /***************************************************************************** 71 -Fuction : Close 72 -Description : 公有函数 73 -Input : 74 -Output : 75 -Return : 76 * Modify Date Version Author Modification 77 * ----------------------------------------------- 78 * 2017/07/12 V1.0.0 Yu Weifeng Created 79 ******************************************************************************/ 80 void Close() 81 { 82 g_tState.Close(); 83 } 84 /***************************************************************************** 85 -Fuction : Run 86 -Description : 公有函数 87 -Input : 88 -Output : 89 -Return : 90 * Modify Date Version Author Modification 91 * ----------------------------------------------- 92 * 2017/07/12 V1.0.0 Yu Weifeng Created 93 ******************************************************************************/ 94 void Run() 95 { 96 g_tState.Run(); 97 } 98 /***************************************************************************** 99 -Fuction : Stop 100 -Description : 公有函数 101 -Input : 102 -Output : 103 -Return : 104 * Modify Date Version Author Modification 105 * ----------------------------------------------- 106 * 2017/07/12 V1.0.0 Yu Weifeng Created 107 ******************************************************************************/ 108 void Stop() 109 { 110 g_tState.Stop(); 111 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : StatePattern.h 5 * Description : 状态模式 6 对各个状态进行管理,也可以改名为StateManage.h 7 为统一名称,本文件也是状态模式的核心故还是 8 命名为StatePattern.h 9 * Created : 2017.07.12. 10 * Author : Yu Weifeng 11 * Function List : 12 * Last Modified : 13 * History : 14 ******************************************************************************/ 15 #ifndef STATE_PATTERN_H 16 #define STATE_PATTERN_H 17 18 19 20 typedef struct State//以电梯运行四种状态举例 21 { 22 // T_FatherState tFatherState;//继承父类,由于c中没有super关键字 23 void (*Open)();//子类内部函数要初始化后才能使用父类的,除非初始化后再设置状态 24 void (*Close)();//为了封装,内部函数就直接调用上下文类设置状态,不使用继承 25 void (*Run)();//也是由于C中只有一个上下文Context,才可以这么做 26 void (*Stop)(); 27 }T_State;//对各种状态的行为进行抽象后的抽象接口 28 29 typedef struct FatherState//抽象出子类统一会设置上下状态函数 30 { 31 //void (*SetContext)(T_StateContext *i_ptStateContext);//由于面向对象语言中 32 //每个子类new的时候都会有一个Context引用产生,切换状态时, 33 //就需要要设置context(下一个子类才能使用context来设置下一态), 34 //而C中只有一个,所以不需要 35 void (*SetState)(T_State *i_ptState);//供状态设置下一状态使用 36 void (*GetState)(T_State *o_ptState); 37 }T_FatherState; 38 39 typedef struct StateContext//因为状态需要切换所以需要上下文类 40 { 41 void (*SetState)(T_State *i_ptState);//供状态设置下一状态使用 42 void (*GetState)(T_State *o_ptState); 43 void (*Open)();//内部不加入状态的静态对象,因为增加的话结构体会过于臃肿 44 void (*Close)();//而且不加入使用更灵活,同时C的对象都是函数指针不费内存 45 void (*Run)(); 46 void (*Stop)(); 47 }T_StateContext; 48 49 50 51 52 53 54 void SetState(T_State *i_ptState); 55 void GetState(T_State *o_ptState); 56 void Open(); 57 void Close(); 58 void Run(); 59 void Stop(); 60 #define newStateContext {SetState,GetState,Open,Close,Run,Stop}; 61 62 63 64 65 66 void RunningStateOpen(); 67 void RunningStateClose(); 68 void RunningStateRun(); 69 void RunningStateStop(); 70 #define newRunningState {RunningStateOpen,RunningStateClose,RunningStateRun,RunningStateStop} 71 72 void StoppingStateOpen(); 73 void StoppingStateClose(); 74 void StoppingStateRun(); 75 void StoppingStateStop(); 76 #define newStoppingState {StoppingStateOpen,StoppingStateClose,StoppingStateRun,StoppingStateStop} 77 78 void ClosingStateOpen(); 79 void ClosingStateClose(); 80 void ClosingStateRun(); 81 void ClosingStateStop(); 82 #define newClosingState {ClosingStateOpen,ClosingStateClose,ClosingStateRun,ClosingStateStop} 83 84 void OpenningStateOpen(); 85 void OpenningStateClose(); 86 void OpenningStateRun(); 87 void OpenningStateStop(); 88 #define newOpenningState {OpenningStateOpen,OpenningStateClose,OpenningStateRun,OpenningStateStop} 89 90 91 92 #endif
II、具体状态角色(各个状态实现同一个接口)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : ClosingState.c 5 * Description : 关闭状态下的各种行为 6 * Created : 2017.07.12. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #include"stdio.h" 13 #include"malloc.h" 14 #include"stdlib.h" 15 #include"string.h" 16 #include"StatePattern.h" 17 18 19 20 21 22 /***************************************************************************** 23 -Fuction : ClosingStateOpen 24 -Description : 公有函数 25 -Input : 26 -Output : 27 -Return : 28 * Modify Date Version Author Modification 29 * ----------------------------------------------- 30 * 2017/07/12 V1.0.0 Yu Weifeng Created 31 ******************************************************************************/ 32 void ClosingStateOpen() 33 { 34 T_StateContext tStateContext=newStateContext; 35 T_State tState=newOpenningState; 36 tStateContext.SetState(&tState);//切换状态 37 tStateContext.GetState(&tState); 38 tState.Open();//执行,逻辑上过度 到下一态 39 } 40 /***************************************************************************** 41 -Fuction : ClosingStateClose 42 -Description : 公有函数 43 -Input : 44 -Output : 45 -Return : 46 * Modify Date Version Author Modification 47 * ----------------------------------------------- 48 * 2017/07/12 V1.0.0 Yu Weifeng Created 49 ******************************************************************************/ 50 void ClosingStateClose() 51 { 52 printf("Lift door close!\r\n"); 53 } 54 /***************************************************************************** 55 -Fuction : ClosingStateRun 56 -Description : 公有函数 57 -Input : 58 -Output : 59 -Return : 60 * Modify Date Version Author Modification 61 * ----------------------------------------------- 62 * 2017/07/12 V1.0.0 Yu Weifeng Created 63 ******************************************************************************/ 64 void ClosingStateRun() 65 { 66 T_StateContext tStateContext=newStateContext; 67 T_State tState=newRunningState; 68 tStateContext.SetState(&tState);//切换状态 69 tStateContext.GetState(&tState); 70 tState.Run();//执行,逻辑上过度 到下一态 71 } 72 /***************************************************************************** 73 -Fuction : ClosingStateStop 74 -Description : 公有函数 75 -Input : 76 -Output : 77 -Return : 78 * Modify Date Version Author Modification 79 * ----------------------------------------------- 80 * 2017/07/12 V1.0.0 Yu Weifeng Created 81 ******************************************************************************/ 82 void ClosingStateStop() 83 { 84 T_StateContext tStateContext=newStateContext; 85 T_State tState=newStoppingState; 86 tStateContext.SetState(&tState);//切换状态 87 tStateContext.GetState(&tState); 88 tState.Stop();//执行,逻辑上过度 到下一态 89 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : OpenningState.c 5 * Description : 开门状态下的各种行为 6 * Created : 2017.07.12. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #include"stdio.h" 13 #include"malloc.h" 14 #include"stdlib.h" 15 #include"string.h" 16 #include"StatePattern.h" 17 18 19 20 21 22 /***************************************************************************** 23 -Fuction : OpenningStateOpen 24 -Description : 公有函数 25 -Input : 26 -Output : 27 -Return : 28 * Modify Date Version Author Modification 29 * ----------------------------------------------- 30 * 2017/07/12 V1.0.0 Yu Weifeng Created 31 ******************************************************************************/ 32 void OpenningStateOpen() 33 { 34 printf("Lift door open!\r\n"); 35 } 36 /***************************************************************************** 37 -Fuction : OpenningStateClose 38 -Description : 公有函数 39 -Input : 40 -Output : 41 -Return : 42 * Modify Date Version Author Modification 43 * ----------------------------------------------- 44 * 2017/07/12 V1.0.0 Yu Weifeng Created 45 ******************************************************************************/ 46 void OpenningStateClose() 47 { 48 T_StateContext tStateContext=newStateContext; 49 T_State tState=newClosingState; 50 tStateContext.SetState(&tState);//切换状态 51 tStateContext.GetState(&tState); 52 tState.Close();//执行,逻辑上过度 到下一态 53 } 54 /***************************************************************************** 55 -Fuction : OpenningStateRun 56 -Description : 门开肯定不运行 57 -Input : 58 -Output : 59 -Return : 60 * Modify Date Version Author Modification 61 * ----------------------------------------------- 62 * 2017/07/12 V1.0.0 Yu Weifeng Created 63 ******************************************************************************/ 64 void OpenningStateRun() 65 { 66 67 } 68 /***************************************************************************** 69 -Fuction : OpenningStateStop 70 -Description : 门开肯定停止了 71 -Input : 72 -Output : 73 -Return : 74 * Modify Date Version Author Modification 75 * ----------------------------------------------- 76 * 2017/07/12 V1.0.0 Yu Weifeng Created 77 ******************************************************************************/ 78 void OpenningStateStop() 79 { 80 81 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : RunningState.c 5 * Description : 运行状态下的各种行为 6 * Created : 2017.07.12. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #include"stdio.h" 13 #include"malloc.h" 14 #include"stdlib.h" 15 #include"string.h" 16 #include"StatePattern.h" 17 18 19 20 21 22 /***************************************************************************** 23 -Fuction : RunningStateOpen 24 -Description : 运行不能打开 25 -Input : 26 -Output : 27 -Return : 28 * Modify Date Version Author Modification 29 * ----------------------------------------------- 30 * 2017/07/12 V1.0.0 Yu Weifeng Created 31 ******************************************************************************/ 32 void RunningStateOpen() 33 { 34 } 35 /***************************************************************************** 36 -Fuction : RunningStateClose 37 -Description : 运行肯定关闭 38 -Input : 39 -Output : 40 -Return : 41 * Modify Date Version Author Modification 42 * ----------------------------------------------- 43 * 2017/07/12 V1.0.0 Yu Weifeng Created 44 ******************************************************************************/ 45 void RunningStateClose() 46 { 47 48 } 49 /***************************************************************************** 50 -Fuction : RunningStateRun 51 -Description : 公有函数 52 -Input : 53 -Output : 54 -Return : 55 * Modify Date Version Author Modification 56 * ----------------------------------------------- 57 * 2017/07/12 V1.0.0 Yu Weifeng Created 58 ******************************************************************************/ 59 void RunningStateRun() 60 { 61 printf("Lift door run!\r\n"); 62 } 63 /***************************************************************************** 64 -Fuction : RunningStateStop 65 -Description : 公有函数 66 -Input : 67 -Output : 68 -Return : 69 * Modify Date Version Author Modification 70 * ----------------------------------------------- 71 * 2017/07/12 V1.0.0 Yu Weifeng Created 72 ******************************************************************************/ 73 void RunningStateStop() 74 { 75 T_StateContext tStateContext=newStateContext; 76 T_State tState=newStoppingState; 77 tStateContext.SetState(&tState);//切换状态 78 tStateContext.GetState(&tState); 79 tState.Stop();//执行,逻辑上过度 到下一态 80 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /***************************************************************************** 2 * Copyright (C) 2017-2018 Hanson Yu All rights reserved. 3 ------------------------------------------------------------------------------ 4 * File Module : StoppingState.c 5 * Description : 停止状态下的各种行为 6 * Created : 2017.07.12. 7 * Author : Yu Weifeng 8 * Function List : 9 * Last Modified : 10 * History : 11 ******************************************************************************/ 12 #include"stdio.h" 13 #include"malloc.h" 14 #include"stdlib.h" 15 #include"string.h" 16 #include"StatePattern.h" 17 18 19 20 21 22 /***************************************************************************** 23 -Fuction : StoppingStateOpen 24 -Description : 公有函数 25 -Input : 26 -Output : 27 -Return : 28 * Modify Date Version Author Modification 29 * ----------------------------------------------- 30 * 2017/07/12 V1.0.0 Yu Weifeng Created 31 ******************************************************************************/ 32 void StoppingStateOpen() 33 { 34 T_StateContext tStateContext=newStateContext; 35 T_State tState=newOpenningState; 36 tStateContext.SetState(&tState);//切换状态 37 tStateContext.GetState(&tState); 38 tState.Open();//执行,逻辑上过度 到下一态 39 40 } 41 /***************************************************************************** 42 -Fuction : StoppingStateClose 43 -Description : 停止本来门就是关的 44 -Input : 45 -Output : 46 -Return : 47 * Modify Date Version Author Modification 48 * ----------------------------------------------- 49 * 2017/07/12 V1.0.0 Yu Weifeng Created 50 ******************************************************************************/ 51 void StoppingStateClose() 52 { 53 54 } 55 /***************************************************************************** 56 -Fuction : StoppingStateRun 57 -Description : 停止接下来再运行 58 -Input : 59 -Output : 60 -Return : 61 * Modify Date Version Author Modification 62 * ----------------------------------------------- 63 * 2017/07/12 V1.0.0 Yu Weifeng Created 64 ******************************************************************************/ 65 void StoppingStateRun() 66 { 67 T_StateContext tStateContext=newStateContext; 68 T_State tState=newRunningState; 69 tStateContext.SetState(&tState);//切换状态 70 tStateContext.GetState(&tState); 71 tState.Run();//执行,逻辑上过度 到下一态 72 } 73 /***************************************************************************** 74 -Fuction : StoppingStateStop 75 -Description : 停止动作得到停止状态 76 -Input : 77 -Output : 78 -Return : 79 * Modify Date Version Author Modification 80 * ----------------------------------------------- 81 * 2017/07/12 V1.0.0 Yu Weifeng Created 82 ******************************************************************************/ 83 void StoppingStateStop() 84 { 85 printf("Lift door stop!\r\n"); 86 }
3)执行结果:
book@book-desktop:/work/projects/test/DesignPatterns$ gcc -o StatePatternUsage RunningState.c
StoppingState.c OpenningState.c ClosingState.c StatePattern.c StatePatternUsage.c
book@book-desktop:/work/projects/test/DesignPatterns$ ./StatePatternUsage
Lift door open!
Lift door close!
Lift door run!
Lift door stop!
4)详细代码:
https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/BehavioralDesignPatterns/StatePattern
三、使用场景
1.行为随状态的改变而改变的场景
2.条件、分支判断语句的替代者
四、优点
1.结构清晰,将状态转移的逻辑从臃肿的switch语句中分散到了各个类中,避免了过多的switch...case等条件判断
2.遵循设计原则,体现了开闭原则和单一职责原则
3.封装性非常好
五、缺点
1.扩展会导致类膨胀,状态最好不要超过5个