责任链模式是一种软件设计模式,它包含了一些命令对象和一系列的处理对象。每一个处理对象决定它能处理哪些命令对象,它也知道如何将它不能处理的命令对象传递给该链中的下一个处理对象。该模式还描述了往该处理链的末尾添加新的处理对象的方法。责任链模式的UML图如下:
下面是一个用C++描述的责任链模式的例子:
#include <iostream>
#include <string>
using namespace std;
// 抽象类,定义处理请求的接口
class Logger {
public:
static const int DEBUG = 1;
static const int NOTICE = 2;
static const int ERR = 3;
// 设置责任链下一个成员
void setNext(Logger *log)
{
next = log;
}
// 根据优先级决定处理消息或传递给下一个处理者
void message(string msg, int priority)
{
if (priority <= mask)
writeMessage(msg);
else if (next != NULL)
next->message(msg, priority);
}
protected:
int mask;
// The next element in the chain of responsibility
Logger *next;
virtual void writeMessage(string msg) = 0;
};
// 具体处理者
class StdoutLogger : public Logger {
public:
StdoutLogger(int m)
{
mask = m;
}
protected:
void writeMessage(string msg)
{
cout << "Writting to stdout: " << msg << endl;
}
};
// 具体处理者
class EmailLogger : public Logger {
public:
EmailLogger(int m)
{
mask = m;
}
protected:
void writeMessage(string msg)
{
cout << "Sending via email: " << msg << endl;
}
};
// 具体处理者
class StderrLogger : public Logger
{
public:
StderrLogger(int m)
{
mask = m;
}
protected:
void writeMessage(string msg)
{
cout << "Sending to stderr: " << msg << endl;
}
};
int main()
{
Logger *log1 = new StdoutLogger(Logger::DEBUG);
Logger *log2 = new EmailLogger(Logger::NOTICE);
Logger *log3 = new StderrLogger(Logger::ERR);
// Build the chain of responsibility
log1->setNext(log2);
log2->setNext(log3);
// Handled by StdoutLogger
log1->message("Hello world.", Logger::DEBUG);
// Handled by EmailLogger
log1->message("Sending a Email.", Logger::NOTICE);
// Handled by StderrLogger
log1->message("An error has occurred.", Logger::ERR);
system("pause");
return 0;
}
运行结果:
上面的例子中,我们建立了三个处理消息的对象,根据内容的优先级分别把内容输出到标准输出、邮件、标准错误。当一个处理对象无法处理这个等级的内容时,将自动传递给责任链中的下一个处理者处理。也就是说,当客户提交一个请求时,请求是沿着责任链传递直至一个具体的负责处理内容的对象。责任链的优点在于,处理内容的对象是通过链表连接起来的,增加或修改责任链是非常方便灵活的。实际上,责任链模式就是把if-else结构改成了链表结构来处理不同的消息,大大降低了代码的耦合度。
参考:
维基百科
《大话设计模式》第24章