設計模式(十八)——職責鍊模式
一、職責鍊模式簡介
1、職責鍊模式簡介
職責鍊模式(Chain Of Responsibility)使多個對象都有機會處理請求,進而避免請求的發送者和接收者之間的耦合。将可能處理請求的對象連成一條鍊,并沿着這條鍊傳遞請求,直到有一個對象處理請求為止。

2、職責連模式角色
Handler類:職責對象抽象類,定義一個處理請求的接口。
ConcreteHandler類:職責對象具體類,實作具體的處理請求的接口。
3、職責鍊模式優缺點
職責鍊模式的優點:
A、當客戶送出一個請求時,請求是沿鍊傳遞直至有一個ConcreteHandler對象負責處理請求。
B、接收者和發送者都沒有對方的明确資訊,且鍊中的對象自己也并不知道鍊的結構。結果是職責鍊可簡化對象的互相連接配接,僅需要保持一個指向其後繼者的引用,而不需要保持所有的候選接收者的引用。
C、由于是在用戶端來定義鍊的結構,是以使用者可以随時地增加或者修改處理一個請求的結構,增強了給對象指派職責的靈活性。
職責鍊模式的缺點:
一個請求極有可能到了鍊的末端都得不到處理,或者因為沒有正确配置而得不到處理。
4、職責鍊模式使用場景
職責鍊模式使用場景:
A、有多個的對象可以處理一個請求,哪個對象處理該請求運作時刻自動确定。
B、在不明确指定接收者的情況下,向多個對象中的一個送出請求。
C、可處理一個請求的對象集合應被動态指定。
二、職責連模式實作
Handler抽象類:
#ifndef HANDLER_H
#define HANDLER_H
#include <iostream>
using namespace std;
//處理請求的抽象類
class Handler
{
public:
//設定後繼處理請求者
void setSuccessor(Handler* successor)
{
m_successor = successor;
}
//處理請求的接口
virtual void handleRequest(int n) = 0;
protected:
Handler(){}
protected:
Handler* m_successor;//後繼者
};
#endif // HANDLER_H
ConcreteHandlerA具體處理類:
#ifndef CONCRETEHANDLERA_H
#define CONCRETEHANDLERA_H
#include "Handler.h"
//處理請求的具體實作類
class ConcreteHandlerA : public Handler
{
public:
void handleRequest(int n)
{
if(n < 1000)
{
cout << "ConcreteHandlerA::handleRequest n = " << n << endl;
}
else//如果n>1000,由後繼者處理請求
{
if(m_successor)
m_successor->handleRequest(n);
}
}
};
#endif // CONCRETEHANDLERA_H
ConcreteHandlerB具體處理類:
#ifndef CONCRETEHANDLERB_H
#define CONCRETEHANDLERB_H
#include "Handler.h"
//處理請求的具體實作類
class ConcreteHandlerB : public Handler
{
public:
void handleRequest(int n)
{
cout << "ConcreteHandlerB::handleRequest n = " << n << endl;
}
};
#endif // CONCRETEHANDLERB_H
客戶調用程式:
#include "Handler.h"
#include "ConcreteHandlerA.h"
#include "ConcreteHandlerB.h"
int main()
{
Handler* a = new ConcreteHandlerA();
Handler* b = new ConcreteHandlerB();
a->setSuccessor(b);
a->handleRequest(200);
a->handleRequest(1200);
delete a,b;
return 0;
}
三、職責鍊模式執行個體
公司中對于請假、加薪等請求有不同的處理流程,不同的請求需要由經理、技術總監、總經理處理。但所有的請求必須送出給經理,如果經理沒有權限,轉給技術總監,技術總監沒有權限,轉給總經理處理。
Request請求類:
#ifndef REQUEST_H
#define REQUEST_H
#include <string>
using namespace std;
//請求
class Request
{
public:
void setType(string type)
{
m_requestType = type;
}
string getType()
{
return m_requestType;
}
void setContent(string content)
{
m_requestContent = content;
}
string getContent()
{
return m_requestContent;
}
void setNumber(int n)
{
m_number = n;
}
int getNumber()
{
return m_number;
}
private:
string m_requestType;//請求類型
string m_requestContent;//請求内容
int m_number;//數量
};
#endif // REQUEST_H
Manager處理請求的抽象類:
#ifndef MANAGER_H
#define MANAGER_H
#include <string>
#include <iostream>
#include "Request.h"
using namespace std;
//Handler抽象類
class Manager
{
public:
~Manager()
{
if(m_superior != NULL)
delete m_superior;
}
//處理請求接口
virtual void requestApplication(Request* request) = 0;
//設定上級
void setSuperior(Manager* superior)
{
m_superior = superior;
}
protected:
Manager(string name)
{
m_name = name;
m_superior = NULL;
}
protected:
string m_name;//管理者姓名
Manager* m_superior;//管理者的上級
};
#endif // MANAGER_H
CommonManager處理請求的具體類:
#ifndef COMMONMANAGER_H
#define COMMONMANAGER_H
#include "Manager.h"
//Handler具體實作類,處理請求的具體對象,經理
class CommonManager : public Manager
{
public:
CommonManager(string name):Manager(name){}
//請求處理函數
void requestApplication(Request* request)
{
if(request->getType() == "ask for leave" && request->getNumber() <= 2)
{
cout << m_name << ":" << request->getContent() << " number:"
<< request->getNumber() << "day approval" << endl;
}
else
{
if(m_superior != NULL)
m_superior->requestApplication(request);
}
}
};
#endif // COMMONMANAGER_H
Majordomo處理請求的具體類:
#ifndef MAJORDOMO_H
#define MAJORDOMO_H
#include "Manager.h"
//Handler具體實作類,處理請求的具體對象,技術總監
class Majordomo : public Manager
{
public:
Majordomo(string name):Manager(name){}
//處理請求函數
void requestApplication(Request* request)
{
if(request->getType() == "ask for leave" && request->getNumber() <= 5)
{
cout << m_name << ":" << request->getContent() << " number:"
<< request->getNumber() << "day approval" << endl;
}
else
{
if(m_superior != NULL)
m_superior->requestApplication(request);
}
}
};
#endif // MAJORDOMO_H
GeneralManager處理請求的具體類:
#ifndef GENERALMANAGER_H
#define GENERALMANAGER_H
#include "Manager.h"
//Handler具體實作類,處理請求的具體對象,總經理
class GeneralManager : public Manager
{
public:
GeneralManager(string name):Manager(name){}
//處理請求函數
void requestApplication(Request* request)
{
if(request->getType() == "ask for leave")
{
cout << m_name << ":" << request->getContent() << " number:"
<< request->getNumber() << "day approval" << endl;
}
else if(request->getType() == "ask for a raise" && request->getNumber() <= 1000)
{
cout << m_name << ":" << request->getContent() << " number:"
<< request->getNumber() << " approval" << endl;
}
else if(request->getType() == "ask for a raise" && request->getNumber() > 1000)
{
cout << m_name << ":" << request->getContent() << " number:"
<< request->getNumber() << " rejected" << endl;
}
}
};
#endif // GENERALMANAGER_H
#include "Manager.h"
#include "CommonManager.h"
#include "Majordomo.h"
#include "GeneralManager.h"
int main()
{
Manager* li = new CommonManager("Li");
Manager* zhang = new Majordomo("zhang");
Manager* wang = new GeneralManager("wang");
li->setSuperior(zhang);//設定CommonManager上級為Majordomo
zhang->setSuperior(wang);//設定Majordomo上級為GeneralManager
Request request1;
request1.setType("ask for leave");//請假
request1.setContent("xiaoming ask for leave");
request1.setNumber(1);
li->requestApplication(&request1);
Request request2;
request2.setType("ask for a raise");//加薪
request2.setContent("xiaohong ask for a raise");
request2.setNumber(1000);
li->requestApplication(&request2);
Request request3;
request3.setType("ask for a raise");//加薪
request3.setContent("xiaozhang ask for a raise");
request3.setNumber(2000);
li->requestApplication(&request3);
Request request4;
request4.setType("ask for leave");//請假
request4.setContent("xiaozhang ask for leave");
request4.setNumber(5);
li->requestApplication(&request4);
delete li,zhang,wang;
return 0;
}