设计模式——责任链模式
文章目錄
- 一、基本概念
- 1.定義
- 4.類似背景舉例
- 3.要點
- 二、結構圖
- 三、實例說明
- 1.普通代碼
- 2.責任鏈代碼
一、基本概念
1.定義
使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系。將這些對象連成一條鏈,并沿著這條鏈傳遞請求,直到有一個對象處理它為止。
4.類似背景舉例
請求流程,1 天內需要主程序批準,3 天內需要項目經理批準,3 天以上需要老板批準;
3.要點
①解耦請求方和處理方,請求方不知道請求是如何被處理,處理方的組成是由相互獨立的子處理構成,子處理流程通過鏈表的方式連接,子處理請求可以按任意順序組合。
②責任鏈請求強調請求最終由一個子處理流程處理;通過了各個子處理條件判斷。
③責任鏈擴展就是功能鏈,功能鏈強調的是,一個請求依次經由功能鏈中的子處理流程處理。
④將職責以及職責順序運行進行抽象,那么職責變化可以任意擴展,同時職責順序也可以任意擴展。
二、結構圖
HandleA和 HandleB是通過指針的指向低度耦合的。結構圖一開始看不太懂,但是等代碼懂了再來看結構圖就恍然大悟了。
三、實例說明
1.普通代碼
比如說我們需要模擬公司里的請假批準模式,先給上一層領導遞請假條,一層領導沒權利批準的話再向上一層遞交…
普通代碼:
普通代碼缺點:所有的人和處理方式都被封裝到一個類里面,而且如果有人的職責發生變化(比如項目經歷的權力 擴大到可以批10天的假),那么我們就需要去修改這一整個類。除此之外,如果以后新增加職位(比如如果新增老板秘書,項目經理秘書可以批準假期請求的話),那么我們也需要在原來的大類中修改增加代碼。顯然違背了開閉原則,而且由于在一個類里賣弄,所以耦合度極高。可以通過類比現實中層層上報的實際情況結合鏈表使用的方式解決這個問題,即責任鏈模式。
2.責任鏈代碼
責任鏈模式代碼:
#include<iostream> #include <string> using namespace std;class Context { public:string name;int day; };class IHandler { public:void SetNextHandler(IHandler* Handler){this->next = Handler;}bool Handler(const Context& ctx) {//能批準就自己批準if (CanHandler(ctx)) {return HandlerRequest(ctx);}//不能批準就遞交給上面領導else if(GetNextHandler()){return GetNextHandler()->Handler(ctx);}//到了最頂層,仍然沒人批準else {cout << "你的假期無人批準" << endl; //or other}return false;}virtual ~IHandler() {} protected:virtual bool HandlerRequest(const Context& ctx) = 0;virtual bool CanHandler(const Context& ctx) = 0;IHandler* GetNextHandler() {return this->next;} private:IHandler* next; };//1天的假期直接在主程序中批準 class HandlerByMainProgram :public IHandler{ public:bool CanHandler(const Context& ctx) {return ctx.day <= 1;}bool HandlerRequest(const Context& ctx) {cout << "主程序批準" << endl;return true;}};//2-3天的假期項目經理批準 class HandlerByProjMgr :public IHandler { public:bool CanHandler(const Context& ctx) {return ctx.day >= 2 && ctx.day <= 3;}bool HandlerRequest(const Context& ctx) {cout << "項目經理批準" << endl;return true;} };//4-20的假期需要老板批準 class HandlerByBoss :public IHandler { public:bool CanHandler(const Context& ctx) {return ctx.day >= 4 && ctx.day <= 20;}bool HandlerRequest(const Context& ctx) {cout << "老板批準" << endl;return true;} };//30天以內的假期,老板秘書都可以批準 class HandlerBySecretary :public IHandler{ public:bool CanHandler(const Context& ctx) {return ctx.day <= 30;}bool HandlerRequest(const Context& ctx) {cout << "秘書處理了你的假期" << endl;return true;} };int main() {IHandler* H0 = new HandlerByMainProgram();IHandler* H1 = new HandlerByProjMgr();IHandler* H2 = new HandlerByBoss();IHandler* H3 = new HandlerBySecretary();//連接順序可以打亂,只不過正常來說,都是有一定要求的//比如說公司請假制度,一般先小組組長批,如果在小組組長權限外,再層層向上申報//如果公司有嚴格的請假制度,對于請假來說,順序打亂不影響最終是否被批準,但是會改變批準的人//比如如果秘書在第一個的話,那么在這里所有能批準的假都將由秘書批準(因為30天以內的假秘書都可以批準)//但是往往權力大的人會先讓手下人解決事情,他解決手下解決不掉的事情H0->SetNextHandler(H1);H1->SetNextHandler(H2);H2->SetNextHandler(H3);Context A;A.name = "xiaomeng";A.day = 2;H0->Handler(A);Context B;B.name = "xiaohua";B.day = 15;H0->Handler(B);Context C;C.name = "xiaopang";C.day = 40;//暫時沒有處理40天假期的操作H0->Handler(C);return 0; }運行結果:
可以看見,把不同的領導之間給解耦了,沒有完全解耦,通過鏈表的方式隱式聯系,這種方式使得她們之間耦合度大大降低,一個領導的權力變化不需要修改其他領導的代碼。
總結
以上是生活随笔為你收集整理的设计模式——责任链模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++——可变模板参数
- 下一篇: 设计模式——装饰器模式