首页 > 代码库 > 设计模式之责任链模式20170717

设计模式之责任链模式20170717

行为型设计模式之责任链模式:

一、含义

责任链模式的核心在"链"上,"链"是由多个处理者(对象)组成的,由这条链传递请求,直到有对象处理它为止(在链中决定谁来处理这个请求),并返回相应的结果

二、代码说明

1.主要有两个角色

1)处理者

它能够对请求做出处理(请求得到处理则直接返回,否则传到下一个处理者),设置下一个处理者(这两个操作可以抽象出来),

同时每个处理者都有一个相应的处理级别,以及具体的处理操作(父类实现请求传递,子类实现请求处理)

2)被处理者(请求者)

主要包括请求以及这个请求对应的处理者级别

 

2.在用C实现过程中也是参考这种思想,以古代女子三从四德举例,具体实现如下:

1)责任链模式使用场景:

技术分享
 1 /*****************************************************************************
 2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
 3 ------------------------------------------------------------------------------
 4 * File Module        :     ResponsibilityChainPatternUsage.c
 5 * Description        :     责任链模式的使用
 6 
 7 book@book-desktop:/work/projects/test/DesignPatterns/ResponsibilityChainPattern$ gcc -o ResponsibilityChainPatternUsage Woman.c Father.c Husband.c Son.c ResponsibilityChainPattern.c ResponsibilityChainPatternUsage.c 
 8 book@book-desktop:/work/projects/test/DesignPatterns/ResponsibilityChainPattern$ ./ResponsibilityChainPatternUsage
 9 女儿向父亲请示:
10 女儿的请求是:我要出去逛街
11 父亲的答复是:同意
12 母亲向儿子请示:
13 女儿的请求是:我要出去逛街
14 儿子的答复是:同意
15 
16 * Created            :     2017.07.14.
17 * Author            :     Yu Weifeng
18 * Function List         :     
19 * Last Modified     :     
20 * History            :     
21 ******************************************************************************/
22 #include"stdio.h"
23 #include"malloc.h"
24 #include"stdlib.h"
25 #include"string.h"
26 #include"ResponsibilityChainPattern.h"
27 
28 
29 
30 
31 /*****************************************************************************
32 -Fuction        : main
33 -Description    : 
34 -Input            : 
35 -Output         : 
36 -Return         : 
37 * Modify Date      Version         Author           Modification
38 * -----------------------------------------------
39 * 2017/07/14    V1.0.0         Yu Weifeng       Created
40 ******************************************************************************/
41 int main(int argc,char **argv)
42 {
43     T_Handle tFatherHandle=newFatherHandle;
44     T_Handle tHusbandHandle=newHusbandHandle;
45     T_Handle tSonHandle=newSonHandle;
46 
47     T_Woman tWoman=newWoman;
48     tFatherHandle.SetNextHandle(&tHusbandHandle);
49     tHusbandHandle.SetNextHandle(&tSonHandle);
50 
51     tFatherHandle.tFatherHandle.HandleMessage(&tWoman,&tFatherHandle);
52 
53     tWoman.SetType(SON_HANDLE_LEVEL);
54     tFatherHandle.tFatherHandle.HandleMessage(&tWoman,&tFatherHandle);
55     
56     return 0;
57 }
ResponsibilityChainPatternUsage.c

一般会有一个封装类对责任模式进行封装,也就是替代场景类,直接返回链中第一个处理者,具体链的设置不需要高层次模块关系,这样,更简化了高层次模块的调用,减少模块间的耦合。

2)被调用者:

技术分享
 1 /*****************************************************************************
 2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
 3 ------------------------------------------------------------------------------
 4 * File Module        :     ResponsibilityChainPattern.c
 5 * Description        :     责任链模式
 6                         以古代女子三从四德举例,女子先请求父亲,
 7                         父亲不处理则丈夫处理,丈夫不处理则儿子
 8                         处理,处理完可直接返回
 9 
10 * Created            :     2017.07.14.
11 * Author            :     Yu Weifeng
12 * Function List         :     
13 * Last Modified     :     
14 * History            :     
15 ******************************************************************************/
16 #include"stdio.h"
17 #include"malloc.h"
18 #include"stdlib.h"
19 #include"string.h"
20 #include"ResponsibilityChainPattern.h"
21 
22 
23 //static T_Handle g_tNextHandle[HANDLE_NUMBER]={NULL};//由于C类中的成员变量是静态的,所以放到子类中
24 //static int g_iHandleNum=0;//如果放在父类,则需要定义为数组并定义长度与使用长度
25 /*****************************************************************************
26 -Fuction        : HandleMessage
27 -Description    : 公有函数
28 -Input            : 
29 -Output         : 
30 -Return         : 
31 * Modify Date      Version         Author           Modification
32 * -----------------------------------------------
33 * 2017/07/14      V1.0.0         Yu Weifeng       Created
34 ******************************************************************************/
35 void HandleMessage(T_Woman *i_ptWoman,T_Handle *i_ptThis)
36 {
37     if(i_ptThis->GetLevel()==i_ptWoman->GetType())
38     {
39         i_ptThis->Handle(i_ptWoman);//调用子类的处理
40     }
41     else
42     {
43         if(i_ptThis->GetNextHandle()!=NULL)
44         {
45             i_ptThis->GetNextHandle()->tFatherHandle.HandleMessage(i_ptWoman,i_ptThis->GetNextHandle());
46         }
47         else
48         {
49             printf("没地方请示 了,按不同意处理\r\n");
50         }
51     }
52 }
ResponsibilityChainPattern.c
技术分享
 1 /*****************************************************************************
 2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
 3 ------------------------------------------------------------------------------
 4 * File Module        :     ResponsibilityChainPattern.h
 5 * Description        :     责任链模式
 6                                     
 7 * Created            :     2017.07.13.
 8 * Author            :     Yu Weifeng
 9 * Function List         :     
10 * Last Modified     :     
11 * History            :     
12 ******************************************************************************/
13 #ifndef RESPONSIBILITY_CHAIN_PATTERN_H
14 #define RESPONSIBILITY_CHAIN_PATTERN_H
15 
16 
17 #define FATHER_HANDLE_LEVEL        1
18 #define HUSBAND_HANDLE_LEVEL    2
19 #define SON_HANDLE_LEVEL            3
20 
21 #define HANDLE_NUMBER    3
22 
23 
24 typedef struct Woman//女性类
25 {
26     int (*GetType)();
27     char *  (*GetRequest)(); 
28     void (*SetType)(int i_iType);//    void (*SetRequest)(char *i_strRequset);
29 }T_Woman;
30 
31 struct Handle;
32 
33 typedef struct HandleManage//统一处理放到父类
34 {
35     void (*HandleMessage)(T_Woman *i_ptWoman,struct Handle *i_ptThis);//struct Handle *i_ptThis用于调用子类的方法
36     //其他面向对象语言,调用子类的实现方法可直接调用
37     //父类定义的子类需要实现的抽象方法即可
38 
39 }T_HandleManage;
40 
41 typedef struct Handle
42 {//类似抽象类
43     T_HandleManage tFatherHandle;//父类来实现(宏定义保证)
44     void (*Handle)(T_Woman *i_ptWoman);//由子类实现,类似抽象方法//对请求处理
45     int (*GetLevel)();
46     void (*SetNextHandle)(struct Handle *i_ptHandle);//由于C类中的成员变量是静态的,所以放到子类中
47     struct Handle *(*GetNextHandle)();
48 }T_Handle;
49 
50 
51 void HandleMessage(T_Woman *i_ptWoman,T_Handle *i_ptThis);
52 
53 void FatherReponse(T_Woman *i_ptWoman);
54 int GetFatherHandleLevel();
55 void SetFatherNextHandle(T_Handle*i_ptHandle);
56 T_Handle *GetFatherNextHandle();
57 //通过宏定义确保继承关系以及父类的不被覆写
58 #define newFatherHandle {HandleMessage,FatherReponse,GetFatherHandleLevel,SetFatherNextHandle,GetFatherNextHandle}
59 
60 void HusbandReponse(T_Woman *i_ptWoman);
61 int GetHusbandHandleLevel();
62 void SetHusbandNextHandle(T_Handle*i_ptHandle);
63 T_Handle *GetHusbandNextHandle();
64 //通过宏定义确保继承关系以及父类的不被覆写
65 #define newHusbandHandle {HandleMessage,HusbandReponse,GetHusbandHandleLevel,SetHusbandNextHandle,GetHusbandNextHandle}
66 
67 void SonReponse(T_Woman *i_ptWoman);
68 int GetSonHandleLevel();
69 void SetSonNextHandle(T_Handle*i_ptHandle);
70 T_Handle *GetSonNextHandle();
71 //通过宏定义确保继承关系以及父类的不被覆写
72 #define newSonHandle {HandleMessage,SonReponse,GetSonHandleLevel,SetSonNextHandle,GetSonNextHandle}
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 int GetType();
83 char *GetRequest();
84 void SetType(int i_iType);
85 #define newWoman {GetType,GetRequest,SetType}
86 
87 #endif
ResponsibilityChainPattern.h
技术分享
 1 /*****************************************************************************
 2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
 3 ------------------------------------------------------------------------------
 4 * File Module        :     Father.c
 5 * Description        :     责任链模式中的角色
 6                         处理者(女性的父亲)
 7 * Created            :     2017.07.14.
 8 * Author            :     Yu Weifeng
 9 * Function List         :     
10 * Last Modified     :     
11 * History            :     
12 ******************************************************************************/
13 #include"stdio.h"
14 #include"malloc.h"
15 #include"stdlib.h"
16 #include"string.h"
17 #include"ResponsibilityChainPattern.h"
18 
19 static T_Handle g_tFatherNextHandle={NULL};
20 
21 /*****************************************************************************
22 -Fuction        : FatherHandle
23 -Description    : 对女儿请求的回应处理
24 -Input            : 
25 -Output         : 
26 -Return         : 
27 * Modify Date      Version         Author           Modification
28 * -----------------------------------------------
29 * 2017/07/14      V1.0.0         Yu Weifeng       Created
30 ******************************************************************************/
31 void FatherReponse(T_Woman *i_ptWoman)
32 {
33     printf("女儿向父亲请示:\r\n");
34     printf("%s\r\n",i_ptWoman->GetRequest());
35     printf("父亲的答复是:同意\r\n");
36 }
37 
38 /*****************************************************************************
39 -Fuction        : GetFatherHandleLevel
40 -Description    : 
41 -Input            : 
42 -Output         : 
43 -Return         : 
44 * Modify Date      Version         Author           Modification
45 * -----------------------------------------------
46 * 2017/07/14      V1.0.0         Yu Weifeng       Created
47 ******************************************************************************/
48 int GetFatherHandleLevel()
49 {
50     return FATHER_HANDLE_LEVEL;
51 }
52 
53 /*****************************************************************************
54 -Fuction        : GetFatherNextHandle
55 -Description    : 
56 -Input            : 
57 -Output         : 
58 -Return         : 
59 * Modify Date      Version         Author           Modification
60 * -----------------------------------------------
61 * 2017/07/14      V1.0.0         Yu Weifeng       Created
62 ******************************************************************************/
63 T_Handle *GetFatherNextHandle()
64 {
65     return &g_tFatherNextHandle;
66 }
67 
68 /*****************************************************************************
69 -Fuction        : SetFatherNextHandle
70 -Description    : 
71 -Input            : 
72 -Output         : 
73 -Return         : 
74 * Modify Date      Version         Author           Modification
75 * -----------------------------------------------
76 * 2017/07/14      V1.0.0         Yu Weifeng       Created
77 ******************************************************************************/
78 void SetFatherNextHandle(T_Handle*i_ptHandle)
79 {
80     memcpy(&g_tFatherNextHandle,i_ptHandle,sizeof(T_Handle));
81 }
Father.c
技术分享
 1 /*****************************************************************************
 2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
 3 ------------------------------------------------------------------------------
 4 * File Module        :     Husband.c
 5 * Description        :     责任链模式中的角色
 6                         处理者(女性的丈夫)
 7 * Created            :     2017.07.14.
 8 * Author            :     Yu Weifeng
 9 * Function List         :     
10 * Last Modified     :     
11 * History            :     
12 ******************************************************************************/
13 #include"stdio.h"
14 #include"malloc.h"
15 #include"stdlib.h"
16 #include"string.h"
17 #include"ResponsibilityChainPattern.h"
18 
19 
20 
21 
22 static T_Handle g_tHusbandNextHandle={NULL};
23 
24 /*****************************************************************************
25 -Fuction        : HusbandHandle
26 -Description    : 对妻子请求的回应处理
27 -Input            : 
28 -Output         : 
29 -Return         : 
30 * Modify Date      Version         Author           Modification
31 * -----------------------------------------------
32 * 2017/07/14      V1.0.0         Yu Weifeng       Created
33 ******************************************************************************/
34 void HusbandReponse(T_Woman *i_ptWoman)
35 {
36     printf("妻子向丈夫请示:\r\n");
37     printf("%s\r\n",i_ptWoman->GetRequest());
38     printf("丈夫的答复是:同意\r\n");
39 }
40 
41 /*****************************************************************************
42 -Fuction        : GetHusbandHandleLevel
43 -Description    : 
44 -Input            : 
45 -Output         : 
46 -Return         : 
47 * Modify Date      Version         Author           Modification
48 * -----------------------------------------------
49 * 2017/07/14      V1.0.0         Yu Weifeng       Created
50 ******************************************************************************/
51 int GetHusbandHandleLevel()
52 {
53     return HUSBAND_HANDLE_LEVEL;
54 }
55 
56 /*****************************************************************************
57 -Fuction        : GetHusbandNextHandle
58 -Description    : 
59 -Input            : 
60 -Output         : 
61 -Return         : 
62 * Modify Date      Version         Author           Modification
63 * -----------------------------------------------
64 * 2017/07/14      V1.0.0         Yu Weifeng       Created
65 ******************************************************************************/
66 T_Handle *GetHusbandNextHandle()
67 {
68     return &g_tHusbandNextHandle;
69 }
70 
71 /*****************************************************************************
72 -Fuction        : SetHusbandNextHandle
73 -Description    : 
74 -Input            : 
75 -Output         : 
76 -Return         : 
77 * Modify Date      Version         Author           Modification
78 * -----------------------------------------------
79 * 2017/07/14      V1.0.0         Yu Weifeng       Created
80 ******************************************************************************/
81 void SetHusbandNextHandle(T_Handle*i_ptHandle)
82 {
83     memcpy(&g_tHusbandNextHandle,i_ptHandle,sizeof(T_Handle));
84 }
Husband.c
技术分享
 1 /*****************************************************************************
 2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
 3 ------------------------------------------------------------------------------
 4 * File Module        :     Son.c
 5 * Description        :     责任链模式中的角色
 6                         处理者(女性的儿子)
 7 * Created            :     2017.07.14.
 8 * Author            :     Yu Weifeng
 9 * Function List         :     
10 * Last Modified     :     
11 * History            :     
12 ******************************************************************************/
13 #include"stdio.h"
14 #include"malloc.h"
15 #include"stdlib.h"
16 #include"string.h"
17 #include"ResponsibilityChainPattern.h"
18 
19 
20 static T_Handle g_tSonNextHandle={NULL};
21 
22 /*****************************************************************************
23 -Fuction        : SonHandle
24 -Description    : 对母亲请求的回应处理
25 -Input            : 
26 -Output         : 
27 -Return         : 
28 * Modify Date      Version         Author           Modification
29 * -----------------------------------------------
30 * 2017/07/14      V1.0.0         Yu Weifeng       Created
31 ******************************************************************************/
32 void SonReponse(T_Woman *i_ptWoman)
33 {
34     printf("母亲向儿子请示:\r\n");
35     printf("%s\r\n",i_ptWoman->GetRequest());
36     printf("儿子的答复是:同意\r\n");
37 }
38 
39 /*****************************************************************************
40 -Fuction        : GetSonHandleLevel
41 -Description    : 
42 -Input            : 
43 -Output         : 
44 -Return         : 
45 * Modify Date      Version         Author           Modification
46 * -----------------------------------------------
47 * 2017/07/14      V1.0.0         Yu Weifeng       Created
48 ******************************************************************************/
49 int GetSonHandleLevel()
50 {
51     return SON_HANDLE_LEVEL;
52 }
53 
54 /*****************************************************************************
55 -Fuction        : GetSonNextHandle
56 -Description    : 
57 -Input            : 
58 -Output         : 
59 -Return         : 
60 * Modify Date      Version         Author           Modification
61 * -----------------------------------------------
62 * 2017/07/14      V1.0.0         Yu Weifeng       Created
63 ******************************************************************************/
64 T_Handle *GetSonNextHandle()
65 {
66     return &g_tSonNextHandle;
67 }
68 
69 /*****************************************************************************
70 -Fuction        : SetSonNextHandle
71 -Description    : 
72 -Input            : 
73 -Output         : 
74 -Return         : 
75 * Modify Date      Version         Author           Modification
76 * -----------------------------------------------
77 * 2017/07/14      V1.0.0         Yu Weifeng       Created
78 ******************************************************************************/
79 void SetSonNextHandle(T_Handle*i_ptHandle)
80 {
81     memcpy(&g_tSonNextHandle,i_ptHandle,sizeof(T_Handle));
82 }
Son.c
技术分享
 1 /*****************************************************************************
 2 * Copyright (C) 2017-2018 Hanson Yu  All rights reserved.
 3 ------------------------------------------------------------------------------
 4 * File Module        :     Woman.c
 5 * Description        :     责任链模式中的角色
 6                         请求者(女性)
 7 * Created            :     2017.07.14.
 8 * Author            :     Yu Weifeng
 9 * Function List         :     
10 * Last Modified     :     
11 * History            :     
12 ******************************************************************************/
13 #include"stdio.h"
14 #include"malloc.h"
15 #include"stdlib.h"
16 #include"string.h"
17 #include"ResponsibilityChainPattern.h"
18 
19 
20 
21 static int g_iType=FATHER_HANDLE_LEVEL;
22 static char *g_strRequest="女儿的请求是:我要出去逛街";
23 /*****************************************************************************
24 -Fuction        : GetRequest
25 -Description    : 公有函数
26 -Input            : 
27 -Output         : 
28 -Return         : 
29 * Modify Date      Version         Author           Modification
30 * -----------------------------------------------
31 * 2017/07/14       V1.0.0         Yu Weifeng       Created
32 ******************************************************************************/
33 char *GetRequest()
34 {
35     return g_strRequest;
36 }
37 /*****************************************************************************
38 -Fuction        : GetType
39 -Description    : 公有函数
40 -Input            : 
41 -Output         : 
42 -Return         : 
43 * Modify Date      Version         Author           Modification
44 * -----------------------------------------------
45 * 2017/07/14       V1.0.0         Yu Weifeng       Created
46 ******************************************************************************/
47 int GetType()
48 {
49     return g_iType;
50 }
51 /*****************************************************************************
52 -Fuction        : SetType
53 -Description    : 公有函数
54 -Input            : 
55 -Output         : 
56 -Return         : 
57 * Modify Date      Version         Author           Modification
58 * -----------------------------------------------
59 * 2017/07/14       V1.0.0         Yu Weifeng       Created
60 ******************************************************************************/
61 void SetType(int i_iType)
62 {
63     g_iType=i_iType;
64 }
Woman.c

3)执行结果:

book@book-desktop:/work/projects/test/DesignPatterns/ResponsibilityChainPattern$ gcc -o

ResponsibilityChainPatternUsage Woman.c Father.c Husband.c Son.c ResponsibilityChainPattern.c

ResponsibilityChainPatternUsage.c

book@book-desktop:/work/projects/test/DesignPatterns/ResponsibilityChainPattern$

./ResponsibilityChainPatternUsage

女儿向父亲请示:

女儿的请求是:我要出去逛街

父亲的答复是:同意

母亲向儿子请示:

女儿的请求是:我要出去逛街

儿子的答复是:同意

 

4)详细代码:

https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/BehavioralDesignPatterns/ResponsibilityChainPattern

 

三、使用场景

1.请求可以由多个处理者处理,同时要将请求和处理分开时

 

四、优点

非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的(责任链模式核心),处理者可以不用知道请求的全貌。

避免了请求的发送者和接收者之间的耦合关系。

 

五、缺点

1.性能问题

每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。

2.调试不太方便

特别是链比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂

因此需注意:

1.链中节点数量需要控制,避免出现超长链的情况

一般做法是在处理中设置一个最大结点数量,在设置下一个结点中判断是否已经超长,超过则不允许建立。

2.责任链模式和观察者模式的区别

责任链模式和观察者模式最大的区别是,责任链处理完后可以直接返回到最初的结点即根节点。而观察者模式是相邻两个结点结构,即处理完返回时也是返回到上一个结点。

 

设计模式之责任链模式20170717