0. 简介
对于责任链模式,其作为一种行为设计模式, 允许你将请求沿着处理者链进行发送。 收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。这种处理方法类似包与包之间的调用的思路,只是其可以不在主程序中累赘的去申明一堆if else变量使得程序更加臃肿。
相比于创建设计模式的对整体架构进行的设计,和结构设计模式对对象的化繁为简的操作,作为行为设计模式,其需要我们对数据流能够充分的把握,来避免检查代码的混乱不堪。 而每次新增功能都会使其更加臃肿。 修改某个检查步骤有时会影响其他的检查步骤。 最糟糕的是, 当你希望复用这些检查步骤来保护其他系统组件时, 你只能复制部分代码, 因为这些组件只需部分而非全部的检查步骤。
1. 责任链模式示意图
职责链模式指使多个对象多有机会处理请求,避免请求发送者和接受者的耦合关系。将这些接受处理的对象连成一条链,并沿着该链处理请求。
- BaseHandler:抽象基类,用于作为处理请求的接口。如果特定等级的请求该类无法处理,则传递给下一个handler,一般这类情况class内部都是纯虚函数。
- ConcreteHandler(TechnicalSupportHandler, BillingSupportHandler, and GeneralSupportHandler):处理请求,或将请求传递给handler链中的下一个,这样可以通过设计整个逻辑链避免混乱
- Client(RequestorClient):发起请求,一般是放在主程序中传入
2. 示例程序
在所有的行为模式中,都设计的准则为:使用对象的组合而不是对象的继承。责任链模式所描述的是:与其从已有的类中继承新的类,不如让你的类指向一个你要使用的已经存在的类。责任链模式通过对Handler Object的封装能够有效地管理整条数据流(行为)的走向。从而避免过多的继承嵌套,与数据流的混乱。
#include <iostream>
using namespace std;
//抽象处理者
class Handler
{
public:
Handler() { m_pNextHandler = NULL; }
virtual ~Handler() {}
//设置下一个处理者
void SetNextHandler(Handler *successor) { m_pNextHandler = successor; }
//处理请求
virtual void HandleRequest(int days) = 0;
protected:
Handler *m_pNextHandler; // 后继者
};
//具体处理者、主管
class Director :public Handler
{
public:
//处理请求
virtual void HandleRequest(int days)
{
if (days <= 1)
{
cout << "我是主管,有权批准一天假,同意了!" << endl;
}
else
{
m_pNextHandler->HandleRequest(days);
}
}
};
//具体处理者、经理
class Manager :public Handler
{
public:
//处理请求
virtual void HandleRequest(int days)
{
if (days <= 3)
{
cout << "我是经理,有权批准三以下的假,同意了!" << endl;
}
else
{
m_pNextHandler->HandleRequest(days);
}
}
};
//具体处理者、老板
class Boss :public Handler
{
public:
//处理请求
virtual void HandleRequest(int days)
{
if (days <= 7)
{
cout << "我是老板,最多让你请7天假,同意了!" << endl;
}
else
{
cout << "你请的假事假太长了,不同意!" << endl;
}
}
};
//场景
int main()
{
Handler *director = new Director;
Handler *manager = new Manager;
Handler *boss = new Boss;
//设置责任链
director->SetNextHandler(manager);
manager->SetNextHandler(boss);
director->HandleRequest(1);
director->HandleRequest(2);
director->HandleRequest(5);
director->HandleRequest(8);
return 0;
}
/*结果:
我是主管,有权批准一天假,同意了!
我是经理,有权批准三以下的假,同意了
我是老板,最多让你请7天假,同意了!
你请的假事假太长了,不同意!
请按任意键继续. . .*/
3. 责任链的优缺点
责任链模式、 命令模式、 中介者模式和观察者模式用于处理请求发送者和接收者之间的不同连接方式:
- 责任链按照顺序将请求动态传递给一系列的潜在接收者, 直至其中一名接收者对请求进行处理。
- 命令在发送者和请求者之间建立单向连接。
- 中介者清除了发送者和请求者之间的直接连接, 强制它们通过一个中介对象进行间接沟通。
- 观察者允许接收者动态地订阅或取消接收请求。
责任链和装饰模式的类结构非常相似。 两者都依赖递归组合将需要执行的操作传递给一系列对象。 但是, 两者有几点重要的不同之处。
- 责任链的管理者可以相互独立地执行一切操作, 还可以随时停止传递请求。
- 各种装饰可以在遵循基本接口的情况下扩展对象的行为。
- 装饰无法中断请求的传递。
4. 责任链模式改变之多线程异步
我们可以明白,作为行为设计模式,其可以使用多线程并行的方式来实现程序运行时间的节约,而责任链模式其具有清晰地逻辑步骤,这就非常适合线程池线性的数据传输。
// mutex1.cpp 通过互斥体lock与unlock保护共享全局变量
#include <chrono>
#include <mutex>
#include <thread>
#include <iostream>
std::chrono::milliseconds interval(100);
std::mutex mutex;
int job_shared = 0; //两个线程都能修改'job_shared',mutex将保护此变量
int job_exclusive = 0; //只有一个线程能修改'job_exclusive',不需要保护
//此线程只能修改 'job_shared'
void job_1()
{
mutex.lock();
std::this_thread::sleep_for(5 * interval); //令‘job_1’持锁等待
++job_shared;
std::cout << "job_1 shared (" << job_shared << ")\n";
mutex.unlock();
}
// 此线程能修改'job_shared'和'job_exclusive'
void job_2()
{
while (true) { //无限循环,直到获得锁并修改'job_shared'
if (mutex.try_lock()) { //尝试获得锁成功则修改'job_shared'
++job_shared;
std::cout << "job_2 shared (" << job_shared << ")\n";
mutex.unlock();
return;
} else { //尝试获得锁失败,接着修改'job_exclusive'
++job_exclusive;
std::cout << "job_2 exclusive (" << job_exclusive << ")\n";
std::this_thread::sleep_for(interval);
}
}
}
int main()
{
std::thread thread_1(job_1);
std::thread thread_2(job_2);
thread_1.join();
thread_2.join();
getchar();
return 0;
}
5. 参考链接
https://refactoringguru.cn/design-patterns/chain-of-responsibility
https://www.cnblogs.com/hebaichuanyeah/p/5625233.html
评论(0)
您还未登录,请登录后发表或查看评论