定義 **責任鏈模式(Chain of Responsibility Pattern)**中,有一條由請求處理者對象組成的鏈條,每個對象(除最後一個對象外)都持有下一個對象的引用,請求發送者將請求發送給第一個對象,請求就會順著鏈條走下去,直到有對象能夠處理請求。該模式將多個處理者對象解耦,使得請求發 ...
定義
責任鏈模式(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;
}