职责链模式(Chain Of Responsibility)
2016-07-19 12:33
411 查看
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); } }
3)职责链的本质:分离职责,动态组合
相关文章推荐
- 硅谷再次拥抱人工智能,真的是新纪元的开始?
- Error: Failed to load plugin angular: Cannot find module 'eslint-plugin-angular'
- 设置Grails中的domain的字段默认是否允许为空
- 游戏AI设计经验分享——行为树的研究
- main(int argc,char* argv[ ])
- 线程间通信方式(wait和notify的使用)
- 使用aidl的项目结构以及小的注意事项
- ubuntu14.04安装pycurl报错: __main__.ConfigurationError: Could not run curl-config: [Errno 2] No such file or directory
- IntelliJ 创建main函数快捷
- AIX查看sshd状态 启动sshd 关闭sshd
- Handler new Handler()和new Handler(Looper.getMainLooper())的区别
- leetcode--011 Container With Most Water
- hdoj1702ACboy needs your help again!(栈和队列)
- Solaris与AIX操作系统syslog配置
- 朴素贝叶斯学习笔记
- 百度吴恩达:人工智能技术融入业务的两个途径
- Mailserver能发不能收的故障处理
- Kali dpkg-source: warning: failed to verify signature on xxx
- Error Domain=com.alamofire.error.serialization.response Code=-1016 "
- 前端开发人员必须了解的七大技能图谱(http://geek.csdn.net/news/detail/88239)