频道栏目
首页 > 资讯 > 其他综合 > 正文

职责链模式(Chain Of Responsibility)

16-07-20        来源:[db:作者]  
收藏   我要投稿

1. 模式的定义

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

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

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

2. UML图

这里写图片描述

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);
    }
}
相关TAG标签
上一篇:初步编写IDEA\AndroidStudio翻译插件
下一篇:STL概述
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站