首页 > 代码库 > 设计模式之状态模式20170712

设计模式之状态模式20170712

行为型设计模式之状态模式:

一、含义

为每个状态创建与之对应的类(对应的每个类实现同一个接口或继承同一个抽象类,便于统一处理),并且再通过一个类切换状态

 

 

二、代码说明

1.一般包含三个角色抽象状态角色,具体状态角色,以及环境(上下文)角色(负责具体状态的切换)。

具体步骤:

1)定义环境角色,并初始化状态

2)通过环境角色执行行为,同时也就是对应状态的行为被执行

3)对应状态的行为的执行分为两种情况:

I、对应状态对应行为执行后,环境角色继续执行行为,调用的还是此状态,此状态的下一个行为(下一状态的行为)被执行,执行中会设置下一态(设置下一态一般都放在抽象父类中,同时由于是继承设置下一态时,也要把对应的环境对象设置进去(继承导致每个子类都有对应的环境类的引用),这样下一个状态对象才能调用环境类中的函数),设置完后再执行对应的下一个行为

II、或对应状态对应行为(函数)执行中,先执行对应的操作,然后设置下一态(显然也要把对应的环境对象设置进去),这样环境角色再次执行行为就是调用下一态的行为(函数)了,而不是还停留在本状态。

两种情况均可以,二选一即可,但是显然第二种方式更简单一点,但对外来看没有差异。

4)接下来再次调用环境角色执行行为,由于前面设置了状态,此时执行的就是下一状态的行为

5)不断调用环境角色执行行为,知道所有的状态行为执行完毕

6)扩展:不断调用环境角色执行行为可以使用建造者模式组装起来进行优化

 

2.在用C实现过程中也是参考这种思想,不过设置下一态不使用继承的方式,以电梯运行状态举例,状态迁移表如下:

 技术分享

具体实现如下:

1)状态模式使用场景:

技术分享
 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 }
StatePatternUsage.c

隐藏(封装)了状态的变化过程,它的切换引起了行为的变化。对外来说,我们只看到行为的发生改变,而不用知道是状态变化引起的。

2)被调用者:

I、环境(上下文)角色(负责具体状态的切换):

技术分享
  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 }
StatePattern.c
技术分享
 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
StatePattern.h

II、具体状态角色(各个状态实现同一个接口)

技术分享
 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 }
ClosingState.c
技术分享
 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 }
OpenningState.c
技术分享
 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 }
RunningState.c
技术分享
 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 }
StoppingState.c

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个

 

设计模式之状态模式20170712