设计模式之责任链模式(Chain of Responsibility )
责任链的目的是通过特定的设计对请求者和接收者之间进行解耦,请求者调用操作的对象,接收者接收请求并执行相关操作,通过解耦请求者不需要关心接收者的接口,同时也可增强职责的灵活性,通过改变链内的成员或调用次序,允许动态新增或删除责任。
作用
责任链模式通过将多个对象连成链式模式,并沿着这个链传递命令或者请求,直到有对象处理它为止。
类视图
实现
我们还是取比较经典的员工请假的例子。员工为请假的请求者,接收者分别从项目经理、部门经理、公司经理这几个层级,员工向上进行请假操作,首先传递给项目经理,项目经理在处理时分为两种情况,如果项目经理人在公司,并且员工的请假天数满足请假的审批权限范围,则给予审批,反之则申请上级进行处理。
当然我们也可以制定自己的特殊规则,比如经理级别的接收者如果人不在,就不能向上进行请求,比如开可以增加请假的事由以供经理进行判断是否满足请假要求等,这些都可以根据实际情况进行扩充,感兴趣可以自己实现。
class DayOffRequest { public: DayOffRequest(int hour) :m_iHour(hour) {} int GetHour() { return m_iHour; } private: int m_iHour; }; class Manager { public: virtual bool HandleRequest(DayOffRequest* request) = 0; }; class PM : public Manager //Project manager项目经理 { public: PM(Manager* handler) :m_Handler(handler) {} bool HandleRequest(DayOffRequest* request) { //在权责范围内给予批准 if (request->GetHour() <= 2) { cout << "PM said : OK" << endl; return true; } else if (m_Handler) //请求上级 { return m_Handler->HandleRequest(request); } else { //无法定夺 cout <<"PM said :no decide" << endl; return false; } } private: Manager* m_Handler; }; class DM : public Manager //Department Manager部门经理 { public: DM(Manager* handler) :m_handler(handler) {} bool HandleRequest(DayOffRequest* request) { if (m_Handler) { if(request->getHour() <=16) { cout <<"DM said :OK" << endl; return true; } else return m_Handler->HandleRequest(request); } else { cout <<"DM said :no decide" << endl; return false; } } private: Manager *m_handler; }; class GM : public Manager //General Manager 总经理 { public: GM():m_handler(NULL) {} bool IsInCompany() { return static_cast<bool>(rand()%2) ; } bool HandleRequest(DayOffRequest* request) { if(IsInCompany()) { cout <<"GM said :OK" << endl; return true; } else { cout <<"GM said :try again latter" << endl; return false; } } private: Manager* m_handler; }; int main() { Manager *general = new GM(); Manager *department = new DM(general); //设置上级 Manager *project = new PM(department); //设置上级 DayOffRequest reqsta(2); //一个员工请假2小时 project->DealWithRequest(&reqsta); DayOffRequest reqstb(20); //另一个员工请假20小时 project->DealWithRequest(&reqstb); delete project; delete department; delete general; }
责任链和观察者模式比较相像,都是进行命令和数据的传递,二者的关键区别是一个是有明确层级和先后关系(也可能不是那么明显),而一个是对象平等的,最通俗的例子就是网络中的DNS路由(链式)和广播模式(群发)的实现,这下大家就明白了吧;
当然也请注意链式结构的效率问题,对于层级最好还是加以控制。
应用场景
- 基于链式的请求和应答的结构;
- 发送者并不知道在链中的哪个对象会响应请求;
- 责任链中的每一个对象都有职责绝对是否对请求进行响应