行为型设计模式之责任链模式:
一、含义
责任链模式的核心在"链"上,"链"是由多个处理者(对象)组成的,由这条链传递请求,直到有对象处理它为止(在链中决定谁来处理这个请求),并返回相应的结果
二、代码说明
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 [email protected]:/work/projects/test/DesignPatterns/ResponsibilityChainPattern$ gcc -o ResponsibilityChainPatternUsage Woman.c Father.c Husband.c Son.c ResponsibilityChainPattern.c ResponsibilityChainPatternUsage.c 8 [email protected]:/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)执行结果:
[email protected]:/work/projects/test/DesignPatterns/ResponsibilityChainPattern$ gcc -o
ResponsibilityChainPatternUsage Woman.c Father.c Husband.c Son.c ResponsibilityChainPattern.c
ResponsibilityChainPatternUsage.c
[email protected]:/work/projects/test/DesignPatterns/ResponsibilityChainPattern$
./ResponsibilityChainPatternUsage
女儿向父亲请示:
女儿的请求是:我要出去逛街
父亲的答复是:同意
母亲向儿子请示:
女儿的请求是:我要出去逛街
儿子的答复是:同意
4)详细代码:
https://github.com/fengweiyu/DesignThinking/tree/master/DesignPatterns/BehavioralDesignPatterns/ResponsibilityChainPattern
三、使用场景
1.请求可以由多个处理者处理,同时要将请求和处理分开时
四、优点
非常显著的优点是将请求和处理分开。请求者可以不用知道是谁处理的(责任链模式核心),处理者可以不用知道请求的全貌。
避免了请求的发送者和接收者之间的耦合关系。
五、缺点
1.性能问题
每个请求都是从链头遍历到链尾,特别是在链比较长的时候,性能是一个非常大的问题。
2.调试不太方便
特别是链比较长,环节比较多的时候,由于采用了类似递归的方式,调试的时候逻辑可能比较复杂
因此需注意:
1.链中节点数量需要控制,避免出现超长链的情况
一般做法是在处理中设置一个最大结点数量,在设置下一个结点中判断是否已经超长,超过则不允许建立。
2.责任链模式和观察者模式的区别
责任链模式和观察者模式最大的区别是,责任链处理完后可以直接返回到最初的结点即根节点。而观察者模式是相邻两个结点结构,即处理完返回时也是返回到上一个结点。