设计模式-责任链模式

责任链模式属于行为模式

Gof定义

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

责任链模式关键点是如何将多个处理节点连成一条链。该模式使一个对象无需知道是其他哪一个对象处理其请求,仅需要知道请求处理的结果。

GOF结构

处理者handler处理它所负责的请求,如果可处理则处理,否则将该请求转发给它的后继者

模式特点

稳定点 多个节点的链式处理流程。

变化点 节点的处理的条件或者处理顺序。

扩展点 动态增删处理节点、调整处理顺序

适用点 一个请求被多个对象处理,并且集合对象应被动态指定。

应用:nginx-处理http流程的11个状态。

场景分析

员工请假流程

1 先向部门主管申请,主管进行处理。

2 部门主管无权限处理时再向他的上级申请比如项目主管,项目主管进行处理。

3 项目主管无权限处理时再向他的上级申请比如区域主管,区域主管进行处理。

4 ...申请依次向下传递,像链条一样,直到有管理者有权限处理为止。

代码实现

leave.cpp

引入模式后实现

leave_ex.cpp

测试

结论:

1 将请假流程作为一个链表,每个处理者作为处理节点。

2 从单节点出发,实现处理功能以及链表关系,完成传递功能。

3 从实现上看引入模式后代码量增大不少,但是设定了一个稳定点,后续不管是修改每个处理的条件、处理的顺序、以及增删处理都会比较简单,也更加符合设计原则。而原始代码修改这些需要不停的调整以及增删if else判断。

代码示例

leave.cpp

#include <iostream>
struct Context{
    int day;
};

class LeaveApply{
public:
   bool Apply(const Context& ctx){
    if(!DepartmentManagerProcess(ctx)){
        if(!ProjectManagerProcess(ctx)){
            if(!RegionalManagerProcess(ctx)){
                return false;
            }
        }
    }
    return true;
   }

private:
    bool DepartmentManagerProcess(const Context& ctx){
        if(ctx.day < 3){
            std::cout << "DepartmentManager agree" << std::endl;  
            return true;
        }
        return false;
    }

    bool ProjectManagerProcess(const Context& ctx){
        if(ctx.day < 10){
            std::cout << "ProjectManager agree" << std::endl;   
            return true;
        }
        return false;
    }

    bool RegionalManagerProcess(const Context& ctx){
        if(ctx.day < 30){
            std::cout << "RegionalManager agree" << std::endl;   
            return true;
        }
        return false;
    }
};

int main(int arc,char** arg){
    std::cout << "leave--" << std::endl;
    Context ctx;
    ctx.day = 15;
    if(arc == 2){
        ctx.day = std::stoi(arg[1]);
    }
    LeaveApply la;
    if(la.Apply(ctx)){
        std::cout <<  ctx.day << " days off success" << std::endl;
    }else{
        std::cout <<  ctx.day << " days off failed" << std::endl;
    }

   return 0;
}

leave_ex.cpp


#include <iostream>
struct Context{
    int day;
};

class Manager{
public:
   virtual bool Process(const Context& ctx) = 0;
   Manager* get_next(){
      return next_;
   }
   void set_next(Manager* manager){
      next_ = manager;
   }

private:
   Manager* next_ = nullptr;
};

class DepartmentManager : public Manager{
public:    
   virtual bool Process(const Context& ctx){
    if(ctx.day < 3){
        std::cout << "DepartmentManager agree" << std::endl; 
        return true;
    }
    return false;
   }
};

class ProjectManager : public Manager{
public:    
   virtual bool Process(const Context& ctx){
    if(ctx.day < 10){
        std::cout << "ProjectManager agree" << std::endl;
        return true;
    }
    return false;
   }
};

class RegionalManager : public Manager{
public:    
   virtual bool Process(const Context& ctx){
    if(ctx.day < 30){
        std::cout << "RegionalManager agree" << std::endl;
        return true;
    }
    return false;
   }
};

class LeaveApply{
public:
   LeaveApply(){
      ManageResponsibility();
   }

   ~LeaveApply(){
    while(manager_){
        auto ptr = manager_;
        manager_ = manager_->get_next();
        delete ptr;
        ptr = nullptr;
    }
   }

   bool Apply(const Context& ctx){
        if(!manager_){
            return false;
        }
        Manager* cur = manager_;
        while(cur){
            if(cur->Process(ctx)){
                return true; 
            }else{
                cur = cur->get_next();
            }
        }
        return false;
   }

private:
    void ManageResponsibility(){
        Manager* dm = new DepartmentManager();
        Manager* pm = new ProjectManager();
        Manager* rm = new RegionalManager();
        dm->set_next(pm);
        pm->set_next(rm);
        manager_ = dm;
    }
  
    Manager* manager_ = nullptr;
};

int main(int arc,char** arg){
    std::cout << "leave2--" << std::endl;

    Context ctx;
    ctx.day = 15;
    if(arc == 2){
        ctx.day = std::stoi(arg[1]);
    }
    LeaveApply la;
    if(la.Apply(ctx)){
        std::cout <<  ctx.day << " days off success" << std::endl;
    }else{
        std::cout <<  ctx.day << " days off failed" << std::endl;
    }

    return 0;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值