1. 模式的定义

考虑这样一个功能:申请聚餐费用的管理,对于聚餐费用的申请,要求处理的逻辑步骤是灵活的。

客户端发出一个请求,会有很多对象都可以处理这个请求,而且不同的对象的处理逻辑是不一样的。对于客户端而言,无所谓谁来处理,反正有对象处理就可以。而且在上述流程中,还希望处理流程是可以灵活变动的,而处理请求的对象需要能方便地修改或者被替换掉,以适应新的业务功能的需要。

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

2. UML图

职责链模式(Chain Of Responsibility)_项目经理 
Handler:定义职责的接口,通常在这里定义处理请求的方法

ConcreteHandler:实现职责的类,在这个类中,对在它职责范围内请求的处理,如果不处理,就继续转发请求给后继者

Client:职责链的客户端,向链上的具体处理对象提交请求,让职责链负责处理

代码:

/**

 * 定义职责对象的接口

 */public abstract class Handler {

    /**

     * 持有下一个处理请求的对象

     */

    protected Handler successor = null;    /**

     * 设置下一个处理请求的对象

     * @param successor 下一个处理请求的对象

     */

    public void setSuccessor(Handler successor){        this.successor = successor;

    }    /**

     * 处理聚餐费用的申请

     * @param user 申请人

     * @param fee 申请的钱数

     * @return 成功或失败的具体通知

     */

    public abstract String handleFeeRequest(String user, double fee);

}public class ProjectManager extends Handler{

 

    public String handleFeeRequest(String user, double fee) {

        String str = "";        //项目经理的权限比较小,只能在500以内

        if(fee < 500){            //为了测试,简单点,只同意小李的

            if("小李".equals(user)){

                str = "项目经理同意"+user+"聚餐费用"+fee+"元的请求";

            }else{                //其他人一律不同意

                str = "项目经理不同意"+user+"聚餐费用"+fee+"元的请求";

            }            return str;

        }else{            //超过500,继续传递给级别更高的人处理

            if(this.successor!=null){                return successor.handleFeeRequest(user, fee);

            }

        }        return str;

    }

}public class DepManager extends Handler{

 

 

    public String handleFeeRequest(String user, double fee) {

        String str = "";        //部门经理的权限只能在1000以内

        if(fee < 1000){            //为了测试,简单点,只同意小李申请的

            if("小李".equals(user)){

                str = "部门经理同意"+user+"聚餐费用"+fee+"元的请求";

            }else{                //其他人一律不同意

                str = "部门经理不同意"+user+"聚餐费用"+fee+"元的请求";

            }            return str;

        }else{            //超过1000,继续传递给级别更高的人处理

            if(this.successor!=null){                return this.successor.handleFeeRequest(user, fee);

            }

        }        return str;

    }

 

}public class GeneralManager extends Handler{

    public String handleFeeRequest(String user, double fee) {

        String str = "";        //总经理的权限很大,只要请求到了这里,他都可以处理

        if(fee >= 1000){            //为了测试,简单点,只同意小李的

            if("小李".equals(user)){

                str = "总经理同意"+user+"聚餐费用"+fee+"元的请求";

            }else{                //其他人一律不同意

                str = "总经理不同意"+user+"聚餐费用"+fee+"元的请求";

            }            return str;

        }else{            //如果还有后继的处理对象,继续传递

            if(this.successor!=null){                return successor.handleFeeRequest(user, fee);

            }

        }        return str;

    }

 

}public class Client {

    public static void main(String[] args) {        //先要组装职责链       

        Handler h1 = new GeneralManager();

        Handler h2 = new DepManager();

        Handler h3 = new ProjectManager();

        h3.setSuccessor(h2);

        h2.setSuccessor(h1);        //开始测试

        String ret1 = h3.handleFeeRequest("小李", 300);

        System.out.println("the ret1="+ret1);   

        String ret2 = h3.handleFeeRequest("小张", 300);

        System.out.println("the ret2="+ret2);   

 

        String ret3 = h3.handleFeeRequest("小李", 600);

        System.out.println("the ret3="+ret3);   

        String ret4 = h3.handleFeeRequest("小张", 600);

        System.out.println("the ret4="+ret4);   

 

        String ret5 = h3.handleFeeRequest("小李", 1200);  

        System.out.println("the ret5="+ret5);   

        String ret6 = h3.handleFeeRequest("小张", 1200);

        System.out.println("the ret6="+ret6);   

    }

}

 

3. 研磨设计模式

在标准的职责链中,只要有对象处理了请求,这个请求就到此为止,不再被传递和处理了。如果要变形使用职责链,就可以让这个请求继续传递,每个职责对象对这个请求进行一定的功能处理,从而形成一个处理请求的功能链。

1) 处理多种请求 
- 不同的业务需要传递的业务数据不同 
- 不同的业务请求的方法不同

/**

 * 通用的请求对象

 */public class RequestModel {

    /**

     * 表示具体的业务类型

     */

    private String type;    /**

     * 通过构造方法把具体的业务类型传递进来

     * @param type 具体的业务类型

     */

    public RequestModel(String type){        this.type = type;

    }    public String getType() {        return type;

    }   

}/**

 * 定义职责对象的接口

 */public abstract class Handler {

    /**

     * 持有下一个处理请求的对象

     */

    protected Handler successor = null;    /**

     * 设置下一个处理请求的对象

     * @param successor 下一个处理请求的对象

     */

    public void setSuccessor(Handler successor){        this.successor = successor;

    }    /**

     * 通用的请求处理方法

     * @param rm 通用的请求对象

     * @return 处理后需要返回的对象

     */

    public Object handleRequest(RequestModel rm){        if(successor != null){            //这个是默认的实现,如果子类不愿意处理这个请求,那就传递到下一个职责对象去处理

            return this.successor.handleRequest(rm);

        }else{

            System.out.println("没有后续处理或者暂时不支持这样的功能处理");            return false;

        }

    }

}/**

 * 封装跟聚餐费用申请业务相关的请求数据

 */public class FeeRequestModel extends RequestModel{

    /**

     * 约定具体的业务类型

     */

    public final static String FEE_TYPE = "fee";    public FeeRequestModel() {        super(FEE_TYPE);

    }    /**

     * 申请人

     */

    private String user;    /**

     * 申请金额

     */

    private double fee;    public String getUser() {        return user;

    }    public void setUser(String user) {        this.user = user;

    }    public double getFee() {        return fee;

    }    public void setFee(double fee) {        this.fee = fee;

    }

}/**

 * 实现项目经理处理聚餐费用申请的对象 

 */public class ProjectManager extends Handler{

    public Object handleRequest(RequestModel rm){        if(FeeRequestModel.FEE_TYPE.equals(rm.getType())){            //表示聚餐费用申请

            return handleFeeRequest(rm);

        }else{            //其他的项目经理暂时不想处理

            return super.handleRequest(rm);

        }

    }    private Object handleFeeRequest(RequestModel rm) {        //先把通用的对象造型回来

        FeeRequestModel frm = (FeeRequestModel)rm;

        String str = "";        //项目经理的权限比较小,只能在500以内

        if(frm.getFee() < 500){            //为了测试,简单点,只同意小李的

            if("小李".equals(frm.getUser())){

                str = "项目经理同意"+frm.getUser()+"聚餐费用"+frm.getFee()+"元的请求";

            }else{                //其他人一律不同意

                str = "项目经理不同意"+frm.getUser()+"聚餐费用"+frm.getFee()+"元的请求";

            }            return str;

        }else{            //超过500,继续传递给级别更高的人处理

            if(this.successor != null){                return successor.handleRequest(rm);

            }

        }        return str;

    }

}/**

 * 封装跟预支差旅费申请业务相关的请求数据

 */public class PreFeeRequestModel extends RequestModel{

    /**

     * 约定具体的业务类型

     */

    public final static String FEE_TYPE = "preFee";    public PreFeeRequestModel() {        super(FEE_TYPE);

    }    /**

     * 申请人

     */

    private String user;    /**

     * 申请金额

     */

    private double fee;    public String getUser() {        return user;

    }    public void setUser(String user) {        this.user = user;

    }    public double getFee() {        return fee;

    }    public void setFee(double fee) {        this.fee = fee;

    }

}/**

 * 实现为项目经理增加预支差旅费用申请处理的功能的子对象,

 * 现在的项目经理既可以处理聚餐费用申请,又可以处理预支差旅费用申请

 */public class ProjectManager2 extends ProjectManager{

    public Object handleRequest(RequestModel rm){        if(PreFeeRequestModel.FEE_TYPE.equals(rm.getType())){            //表示预支差旅费用申请

            return myHandler(rm);

        }else{            //其他的让父类去处理

            return super.handleRequest(rm);

        }

    }    private Object myHandler(RequestModel rm) {        //先把通用的对象造型回来

        PreFeeRequestModel frm = (PreFeeRequestModel)rm;        //项目经理的权限比较小,只能在5000以内

        if(frm.getFee() < 5000){            //工作需要嘛,统统同意

            System.out.println("项目经理同意"+frm.getUser()+"预支差旅费用"+frm.getFee()+"元的请求");            return true;

        }else{            //超过5000,继续传递给级别更高的人处理

            if(this.successor!=null){                return this.successor.handleRequest(rm);

            }

        }        return false;

    }

}public class Client {

    public static void main(String[] args) {        //DepManager的实现与ProjectManager类似

        //DepManager2的实现与ProjectManager2类似

 

        //先要组装职责链       

        Handler h1 = new GeneralManager2();

        Handler h2 = new DepManager2();

        Handler h3 = new ProjectManager2();

        h3.setSuccessor(h2);

        h2.setSuccessor(h1);        //开始测试申请聚餐费用

        FeeRequestModel frm = new FeeRequestModel();

        frm.setFee(300);

        frm.setUser("小李");        //调用处理

        String ret1 = (String)h3.handleRequest(frm);

        System.out.println("ret1="+ret1);        //重新设置申请金额,再调用处理

        frm.setFee(800);        

        h3.handleRequest(frm);

        String ret2 = (String)h3.handleRequest(frm);

        System.out.println("ret2="+ret2);        //重新设置申请金额,再调用处理

        frm.setFee(1600);       

        h3.handleRequest(frm);

        String ret3 = (String)h3.handleRequest(frm);

        System.out.println("ret3="+ret3);        //开始测试申请预支差旅费用

        PreFeeRequestModel pfrm = new PreFeeRequestModel();

        pfrm.setFee(3000);

        pfrm.setUser("小张");        //调用处理

        h3.handleRequest(pfrm);        //重新设置申请金额,再调用处理

        pfrm.setFee(6000);

        h3.handleRequest(pfrm);        //重新设置申请金额,再调用处理

        pfrm.setFee(36000);

        h3.handleRequest(pfrm);

    }

}

 

2) 功能链 
每个职责对象负责处理请求的某一方面的功能,处理完成后,不是停止,而是继续向下传递请求。

/**

 * 封装销售单的数据,简单的示意一些

 */public class SaleModel {

    /**

     * 销售的商品

     */

    private String goods;    /**

     * 销售的数量

     */

    private int saleNum;    public String getGoods() {        return goods;

    }    public void setGoods(String goods) {        this.goods = goods;

    }    public int getSaleNum() {        return saleNum;

    }    public void setSaleNum(int saleNum) {        this.saleNum = saleNum;

    }    public String toString(){        return "商品名称="+goods+",销售数量="+saleNum;

    }

}/**

 * 定义职责对象的接口

 */public abstract class SaleHandler {

    /**

     * 持有下一个处理请求的对象

     */

    protected SaleHandler successor = null;    /**

     * 设置下一个处理请求的对象

     * @param successor 下一个处理请求的对象

     */

    public void setSuccessor(SaleHandler successor){        this.successor = successor;

    }    /**

     * 处理保存销售信息的请求

     * @param user 操作人员

     * @param customer 客户

     * @param saleModel 销售数据

     * @return 是否处理成功

     */

    public abstract boolean sale(String user,String customer,SaleModel saleModel);

}/**

 * 进行权限检查的职责对象

 */public class SaleSecurityCheck extends SaleHandler{

    public boolean sale(String user, String customer, SaleModel saleModel) {        //进行权限检查,简单点,就小李能通过

        if("小李".equals(user)){            return this.successor.sale(user, customer, saleModel);

        }else{

            System.out.println("对不起"+user+",你没有保存销售信息的权限");            return false;

        }       

    }

}/**

 * 进行数据通用检查的职责对象

 */public class SaleDataCheck extends SaleHandler{

    public boolean sale(String user, String customer, SaleModel saleModel) {        //进行数据通用检查,稍麻烦点,每个数据都要检测

        if(user==null || user.trim().length()==0){

            System.out.println("申请人不能为空");            return false;

        }        if(customer==null || customer.trim().length()==0){

            System.out.println("客户不能为空");            return false;

        }        if(saleModel==null ){

            System.out.println("销售商品的数据不能为空");            return false;

        }        if(saleModel.getGoods()==null ||saleModel.getGoods().trim().length()==0){

            System.out.println("销售的商品不能为空");            return false;

        }        if(saleModel.getSaleNum()==0){

            System.out.println("销售商品的数量不能为0");            return false;

        }       

        //如果通过了上面的检测,那就向下继续执行

        return this.successor.sale(user, customer, saleModel);

    }

}/**

 * 进行数据逻辑检查的职责对象

 */public class SaleLogicCheck extends SaleHandler{

    public boolean sale(String user, String customer, SaleModel saleModel) {        //进行数据的逻辑检查,比如检查ID的唯一性,主外键的对应关系等等

        //这里应该检查这种主外键的对应关系,比如销售商品是否存在

        //为了演示简单,直接通过吧

 

        //如果通过了上面的检测,那就向下继续执行

        return this.successor.sale(user, customer, saleModel);

    }

}/**

 * 真正处理销售的业务功能的职责对象

 */public class SaleMgr extends SaleHandler{

    public boolean sale(String user, String customer, SaleModel saleModel) {        //进行真正的业务逻辑处理

        System.out.println(user+"保存了"+customer+"购买 "+saleModel+" 的销售数据");        return true;

    }

}/**

 * 商品销售管理模块的业务处理

 */public class GoodsSaleEbo {

    /**

     * 保存销售信息,本来销售数据应该是多条,太麻烦了,为了演示,简单点

     * @param user 操作人员

     * @param customer 客户

     * @param saleModel 销售数据

     * @return 是否保存成功

     */

    public boolean sale(String user,String customer,SaleModel saleModel){        //如果全部在这里处理,基本的顺序是

        //1:权限检查

        //2:通用数据检查(这个也可能在表现层已经作过了)

        //3:数据逻辑校验

        //4:真正的业务处理

 

        //但是现在通过功能链来做,这里就主要负责构建链

        SaleSecurityCheck ssc = new SaleSecurityCheck();

        SaleDataCheck sdc = new SaleDataCheck();

        SaleLogicCheck slc = new SaleLogicCheck();

        SaleMgr sd = new SaleMgr();

        ssc.setSuccessor(sdc);

        sdc.setSuccessor(slc);

        slc.setSuccessor(sd);        //向链上的第一个对象发出处理的请求

        return ssc.sale(user, customer, saleModel);

    }

}public class Client {

    public static void main(String[] args) {        //创建业务对象

        GoodsSaleEbo ebo = new GoodsSaleEbo();        //准备测试数据

        SaleModel saleModel = new SaleModel();

        saleModel.setGoods("张学友怀旧经典");

        saleModel.setSaleNum(10);        //调用业务功能

        ebo.sale("小李", "张三", saleModel);

        ebo.sale("小张", "李四", saleModel);

    }

}

 

3)职责链的本质:分离职责,动态组合

Java高级架构干货|学习职责链模式(Chain Of Responsibility)_职责链_02职责链模式(Chain Of Responsibility)_客户端_03长按,识别二维码,加关注