C++設計模式專欄:
相關文章系列
設計模式之責任鏈模式(一)-CSDN博客
目錄
1.引言
2.實現(xiàn)方式1
3.實現(xiàn)方式2
4.總結? ? ? ??
1.引言
????????責任鏈設計模式(Chain of Responsibiliy DesignPattern)簡稱職責鏈模式。在GOF的《設計模式:可復用面向?qū)ο筌浖幕A》中,它是這樣定義的:將請求的發(fā)送和接收解耦,讓多個接收對象都有機會處理這個請求;將這些接收對象串成一條鏈,并沿者這條鏈傳遞這個請求,直到鏈上的某個接收對象能夠處理它為止(Avoid coupling the?sender of?a?request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it )。
????????在職責鏈模式中,多個處理器(也就是定義中所說的“接收對象”)依次處理同一個請求。一個請求首先經(jīng)過A處理器處理,然后,這個請求被傳遞給B處理器,B處理器處理完后再將其傳遞給C處理器,以此類推,形成一個鏈條。因為鏈條上的每個處理器各自承擔各自職責,所以稱為職責鏈模式。
????????職責鏈模式有多種實現(xiàn)方式,這里介紹兩種常用的。
2.實現(xiàn)方式1
????????實現(xiàn)方式的代碼如下所示。其中,Handler類是所有處理器類的抽象父類,handle()是抽象方法。每個具體的處理器類(HandlerA、HandlerB)的handle()函數(shù)的代碼結構類似,如果某個處理器能夠處理該請求,就不繼續(xù)往下傳遞;如果它不能處理,則交由后面的處理器處理(也就是調(diào)用successor.handle())。HandlerChain類表示處理器鏈,從數(shù)據(jù)結構的角度來看,它就是一個記錄了鏈頭、鏈尾的鏈表。其中,記錄鏈尾是為了方便添加處理器。
#pragma once
#include <memory>
#include <vector>
class IHandler
{
protected:
IHandler* m_successor;
public:
void setSuccessor(IHandler* successor) {
m_successor = successor;
}
virtual void handle() = 0;
};
class HandlerA : public IHandler
{
public:
//...
//@override
void handle() override {
bool bHandle = false;
//...
if (!bHandle && m_successor) {
m_successor->handle();
}
//...
}
};
class HandlerB : public IHandler
{
public:
//...
//@override
void handle() override {
bool bHandle = false;
//...
if (!bHandle && m_successor) {
m_successor->handle();
}
//...
}
};
class HandlerChain {
private:
IHandler* head = nullptr;
IHandler* tail = nullptr;
public:
void addHandler(IHandler* handler) {
handler->setSuccessor(nullptr);
if (head == nullptr) {
head = handler;
tail = handler;
return;
}
tail->setSuccessor(handler);
tail = handler;
}
void handle() {
if (head != nullptr) {
head->handle();
}
}
};
//使用舉例
int main() {
std::unique_ptr<IHandler> pHandleA(new HandlerA());
std::unique_ptr<IHandler> pHandleB(new HandlerB());
HandlerChain chain;
chain.addHandler(pHandleA.get());
chain.addHandler(pHandleB.get());
chain.handle();
return 1;
}
????????實際上,上面的代碼實現(xiàn)不夠優(yōu)雅,因為處理器類的handle()函數(shù)不僅包含自己的業(yè)務邏輯。還包含對下一個處理器的調(diào)用(對應代碼中的successor.handle())。如果一個不熟悉這種代碼結構的程序員想要在其中添加新的處理器類,那么很有可能忘記在handle()函數(shù)中調(diào)用successor.handle(),這就會導致代碼出現(xiàn)bug。
設計模式之模板方法模式-CSDN博客
????????針對這個問題,我們對代碼進行重構,利用模版方法模式,將調(diào)用successor.handle()的邏輯從處理器中剝離出來,放到抽象父類中。這樣,處理器類只需要實現(xiàn)自己的業(yè)務邏輯。重構之后的代碼如下所示:
class IHandler
{
protected:
IHandler* m_successor;
public:
void setSuccessor(IHandler* successor) {
m_successor = successor;
}
void handle() {
bool bHandled = doHandle();
if (!bHandled && m_successor) {
m_successor->handle();
}
}
protected:
virtual bool doHandle() = 0;
};
class HandlerA : public IHandler
{
protected:
//...
//@override
bool doHandle() override {
bool bHandle = false;
//...
return bHandle;
}
};
class HandlerB : public IHandler
{
protected:
//...
//@override
bool doHandle() override {
bool bHandle = false;
//...
return bHandle;
}
};
class HandlerChain {
private:
IHandler* head = nullptr;
IHandler* tail = nullptr;
public:
void addHandler(IHandler* handler) {
handler->setSuccessor(nullptr);
if (head == nullptr) {
head = handler;
tail = handler;
return;
}
tail->setSuccessor(handler);
tail = handler;
}
void handle() {
if (head != nullptr) {
head->handle();
}
}
};
int main() {
std::unique_ptr<IHandler> pHandleA(new HandlerA());
std::unique_ptr<IHandler> pHandleB(new HandlerB());
HandlerChain chain;
chain.addHandler(pHandleA.get());
chain.addHandler(pHandleB.get());
chain.handle();
return 1;
}
3.實現(xiàn)方式2
????????實現(xiàn)代碼如下所示,這種實現(xiàn)方式更加簡單,其中HandlerChain 類用數(shù)組而非鏈表來保存所有處理器類,并且在HandlerChain類的handle()函數(shù)中,依次調(diào)用每個處理器類的 handle()函數(shù)。
class IHandler
{
public:
virtual bool handle() = 0;
};
class HandlerA : public IHandler
{
public:
//...
//@override
bool handle() override {
bool bHandle = false;
//...
return bHandle;
}
};
class HandlerB : public IHandler
{
public:
//...
//@override
bool handle() override {
bool bHandle = false;
//...
return bHandle;
}
};
class HandlerChain {
private:
std::vector<IHandler*> m_vecHandler;
public:
void addHandler(IHandler* handler) {
m_vecHandler.push_back(handler);
}
void handle() {
for (auto& it : m_vecHandler) {
if (it->handle()) {
break;
}
}
}
};
int main() {
std::unique_ptr<IHandler> pHandleA(new HandlerA());
std::unique_ptr<IHandler> pHandleB(new HandlerB());
HandlerChain chain;
chain.addHandler(pHandleA.get());
chain.addHandler(pHandleB.get());
chain.handle();
return 1;
}
????????在GoF合著的《設計模式:可復用面向?qū)ο筌浖幕A》給出的職責鏈模式的定義中。如果處理器鏈上的某個處理器能夠處理這個請求,就不會繼續(xù)往下傳遞請求。實際上,職責鏈模式還有一種變體,那就是請求會被所有處理器都處理一遍,不存在中途終止的情況。這種變體也有兩種實現(xiàn)方式: 用鏈表存儲處理器類和用數(shù)組存儲處理器類,與上面兩種實現(xiàn)方式類似稍加修改即可。這里只給出用鏈表存儲處理器類的實現(xiàn)方式,代碼如下所示。對于用數(shù)組存儲處理器類的實現(xiàn)方式,讀者可對照上面的實現(xiàn)自行修改。文章來源:http://www.zghlxwxcb.cn/news/detail-859353.html
class IHandler
{
protected:
IHandler* m_successor;
public:
void setSuccessor(IHandler* successor) {
m_successor = successor;
}
void handle() {
doHandle();
if (m_successor) {
m_successor->handle();
}
}
protected:
virtual void doHandle() = 0;
};
class HandlerA : public IHandler
{
protected:
//...
//...
//@override
void doHandle() override {
//...
}
};
class HandlerB : public IHandler
{
protected:
//...
//@override
void doHandle() override {
//...
}
};
class HandlerChain {
private:
IHandler* head = nullptr;
IHandler* tail = nullptr;
public:
void addHandler(IHandler* handler) {
handler->setSuccessor(nullptr);
if (head == nullptr) {
head = handler;
tail = handler;
return;
}
tail->setSuccessor(handler);
tail = handler;
}
void handle() {
if (head != nullptr) {
head->handle();
}
}
};
int main() {
std::unique_ptr<IHandler> pHandleA(new HandlerA());
std::unique_ptr<IHandler> pHandleB(new HandlerB());
HandlerChain chain;
chain.addHandler(pHandleA.get());
chain.addHandler(pHandleB.get());
chain.handle();
return 1;
}
4.總結? ? ? ??
????????盡管我們給出了典型的職責鏈模式的代碼實現(xiàn),但在實際的開發(fā)中,我們還是要具體問題具體對待,因為職責鏈模式的代碼實現(xiàn)會根據(jù)需求的不同而有所變化。實際上,這一點對于有設計模式都適用。文章來源地址http://www.zghlxwxcb.cn/news/detail-859353.html
到了這里,關于設計模式之責任鏈模式(二): 實現(xiàn)方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!