设计模式之责任链模式(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路由(链式)和广播模式(群发)的实现,这下大家就明白了吧;

当然也请注意链式结构的效率问题,对于层级最好还是加以控制。

应用场景

  1. 基于链式的请求和应答的结构;
  2. 发送者并不知道在链中的哪个对象会响应请求;
  3. 责任链中的每一个对象都有职责绝对是否对请求进行响应
优质内容筛选与推荐>>
1、使用Inno Setup 打包jdk、mysql、tomcat、webapp等为一个exe安装包
2、Service Fabric下删除实例并注销应用
3、Miller_Rabin (米勒-拉宾) 素性测试
4、使用JAVA直观感受快速排序与冒泡排序的性能差异
5、C++ 虚指针、成员变量与类对象的偏移地址


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号