定義
責任鏈模式(Chain of Responsibility Pattern)中,有一條由請求處理者物件組成的鏈條,每個物件(除最后一個物件外)都持有下一個物件的參考,請求發送者將請求發送給第一個物件,請求就會順著鏈條走下去,直到有物件能夠處理請求,該模式將多個處理者物件解耦,使得請求發送者只管將請求發送給責任鏈的第一個物件就是了,不用去關心請求具體是如何被處理的,
組成
抽象請求處理者(Abstract Request Handler):定義處理請求的介面,
具體請求處理者(Concrete Request Handler):持有下一個處理者物件的參考,具體實作處理請求的介面,包括將請求處理掉和傳給下一個物件,
客戶端(Client):將請求發送給責任鏈的頭部物件,
舉例
某學校的學生請假審批流程:
天數 <= 3:班主任審批通過;
3 < 天數 <= 7:班主任審批不通過,交給年級組長,年級組長審批通過;
7 < 天數 <= 30:年級組長審批不通過,交給教務處,教務處審批通過;
30 < 天數 <= 60:教務處審批不通過,交給校長,校長審批通過;
天數 > 60:校長審批不通過,
不用責任鏈模式寫出的代碼:
void handleRequest(int days)
{
if (days <= 3)
{
cout << "班主任審批通過," << endl;
}
else
{
cout << "班主任審批不通過,交給年級組長," << endl;
if (days <= 7)
{
cout << "年級組長審批通過," << endl;
}
else
{
cout << "年級組長審批不通過,交給教務處," << endl;
if (days <= 30)
{
cout << "教務處審批通過," << endl;
}
else
{
cout << "教務處審批不通過,交給校長," << endl;
if (days <= 60)
{
cout << "校長審批通過," << endl;
}
else
{
cout << "校長審批不通過," << endl;
}
}
}
}
}
可以看到,這段代碼又是一堆if-else又是層層嵌套的,又臭又長,好難看!更重要的問題是,如果流程需要修改,那業務代碼也需要修改,不符合開閉原則,難以維護和擴展,
那怎么樣提高程式的可擴展性呢?
我們應該把班主任、年級組長等等拆分出來當做請求處理者,并指定一個共同的抽象父類,父類里面定義抽象介面,子類具體實作這些介面,
UML類圖:

代碼:
#include <iostream>
using namespace std;
/** 抽象處理者 */
class AbstractRequestHandler
{
protected:
const char *name;
const int maxDaysLimit;
AbstractRequestHandler *const nextHandler; // 由于鏈條中最后一個處理者沒有下一個處理者,但是c++不像java那樣存在空參考,所以只能用指標了
AbstractRequestHandler(
const char *name,
const int maxDaysLimit,
AbstractRequestHandler *const nextHandler
) :
name(name),
maxDaysLimit(maxDaysLimit),
nextHandler(nextHandler)
{ }
virtual void handleRequest(int days)
{
if (days <= maxDaysLimit)
{
cout << name << "審批通過" << endl;
}
else
{
cout << name << "審批不通過";
if (nextHandler)
{
cout << ",轉交給" << nextHandler->name << endl;
nextHandler->handleRequest(days);
}
}
}
virtual ~AbstractRequestHandler()
{
if (nextHandler)
{
delete nextHandler;
}
}
friend class Client;
};
/** 具體處理者————校長 */
class Principal : public AbstractRequestHandler
{
public:
Principal() : AbstractRequestHandler("校長", 60, nullptr) { }
};
/** 具體處理者————教務處 */
class AcademicAffairsOffice : public AbstractRequestHandler
{
public:
AcademicAffairsOffice() : AbstractRequestHandler("教務處", 30, new Principal) { }
};
// 年級組長、班主任 略
/** 客戶端 */
class Client
{
HeadTeacher headTeacher;
public:
Client() : headTeacher() { }
void sendRequest(int days)
{
headTeacher.handleRequest(days);
}
};
int main()
{
Client client;
int days = 10;
cout << "學生將為期" << days << "天的請求交給班主任" << endl;
client.sendRequest(days);
return 0;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/509647.html
標籤:其他
上一篇:冪等設計詳解
下一篇:原型模式(創建型)
