责任链模式是一种非常容易理解、容易使用的模式。
转载请注明出处:http://www.cnblogs.com/zrtqsk/p/3812454.html,谢谢!
一、介绍
我们先来看一下《研磨设计模式》对责任链模式的定义——使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。
责任链模式的本质是——分离职责,动态组合。
责任链模式是用来解决什么问题的呢?当我们有多个对象可以处理同一请求,但是具体由哪个对象来处理请求是运行时动态确定的,这时候使用责任链模式。责任链模式的核心是一个Handler请求抽象类,它持有一个指向下一个请求的引用。当它满足某个条件的时候,由自己来处理,否则,让下一个请求来处理。说白了就是一个处理器持有另一个处理器的引用,如果自己不能处理,就让另一个处理器处理。我们可以看到,本质上而言,责任链模式更策略模式是很像的,也是实现了方法的复用,不过它多了后续的处理方案。
二、结构
Handler : 定义职责的接口,用来定义判断、处理请求的方法handlerRequest(),同时有一个指向下一个处理者的引用successor。
ConcreteHandler : 实现职责的类。实现在它职权范围内的请求的处理。若不处理,则转发给后继的处理者。
Client : 调用职责接口,像Handler提交请求。
三、我的实现
假设学生需要请假,如果三天假以内,由辅导员处理,如果超过3天假,需要由学院院长处理,如果超过7天假,需要由学校校长处理。但是学生并不知道自己请假需要谁处理,只知道去找辅导员。面对这种情况,怎么实现呢?
1、首先我们要有一个请求类,作为请求的父类,封装请求的通用属性。如下:
package chain_of_responsibility.me; public class Request { private String type; // 类型 private String name; //请求者姓名 private String description; // 描述 public String getName() { return name; } public void setName(String name) { this.name = name; } public Request(String type) { this.type = type; } public String getType() { return type; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } }
2、请假请求继承了它,如下:
package chain_of_responsibility.me; /* * 请假请求 */ public class RequestLeave extends Request { public static final String LEAVE_TYPE = "ask_for_leave"; private int days; public RequestLeave() { super(LEAVE_TYPE); } public int getDays() { return days; } public void setDays(int datys) { this.days = datys; } }
3、然后,就是我们重点的处理器抽象类,用来处理请求,如下:
package chain_of_responsibility.me; public abstract class Handler { protected Handler successor; public void setSuccessor(Handler successor) { this.successor = successor; } protected abstract String handlerRequst(Request request); }
4、接下来就是处理器的实现类,3个处理器——辅导员、院长、校长,如下:
package chain_of_responsibility.me; /* * 辅导员 */ public class HandlerCounsellor extends Handler { @Override protected String handlerRequst(Request request) { if (request.getType().equals(RequestLeave.LEAVE_TYPE)) { // 如果是请假的请求,才处理 return handlerLeaveRequest(request); }else { return "辅导员无法受理此请求!"; } } private String handlerLeaveRequest(Request request) { String returnStr = ""; RequestLeave rl = (RequestLeave) request; if (rl.getDays() <= 3) { // 一旦在3天以内,全部同意 returnStr = "辅导员同意了" + rl.getName() + "的请假!"; } else { if (successor != null) { returnStr = successor.handlerRequst(request); } else { returnStr = "上级领导不在,暂时无法处理!"; } } return returnStr; } }
package chain_of_responsibility.me; /* * 院长 */ public class HandlerDean extends Handler { @Override protected String handlerRequst(Request request) { if (request.getType().equals(RequestLeave.LEAVE_TYPE)) { // 如果是请假的请求,才处理 return handlerLeaveRequest(request); }else { return "院长无法受理此请求!"; } } private String handlerLeaveRequest(Request request) { String returnStr = ""; RequestLeave rl = (RequestLeave) request; if (rl.getDays() <= 7) { // 一旦在7天以内,全部同意 returnStr = "院长同意了" + rl.getName() + "的请假!"; } else { if (successor != null) { returnStr = successor.handlerRequst(request); } else { returnStr = "上级领导不在,暂时无法处理!"; } } return returnStr; } }
package chain_of_responsibility.me; /* * 校长 */ public class HandlerPresident extends Handler { @Override protected String handlerRequst(Request request) { if (request.getType().equals(RequestLeave.LEAVE_TYPE)) { // 如果是请假的请求,才处理 return handlerLeaveRequest(request); } else { return "校长无法受理此请求!"; } } private String handlerLeaveRequest(Request request) { String returnStr = ""; RequestLeave rl = (RequestLeave) request; returnStr = "校长同意了" + rl.getName() + "的请假!"; //不问天数、全部同意! return returnStr; } }
4、OK,下面是测试:
package chain_of_responsibility.me; public class Client { public static void main(String[] args) { Handler counsellor = new HandlerCounsellor(); // 辅导员 Handler dean = new HandlerDean(); // 院长 Handler president = new HandlerPresident(); // 校长 // 拼装处理链 counsellor.setSuccessor(dean); dean.setSuccessor(president); // 3个不同请求 RequestLeave request1 = new RequestLeave(); RequestLeave request2 = new RequestLeave(); RequestLeave request3 = new RequestLeave(); request1.setDays(2); request1.setName("张三"); request2.setDays(5); request2.setName("李四"); request3.setDays(9); request3.setName("王五"); // 请求 System.out.println(counsellor.handlerRequst(request1)); System.out.println(counsellor.handlerRequst(request2)); System.out.println(counsellor.handlerRequst(request3)); } }
5、结果如下:
辅导员同意了张三的请假!
院长同意了李四的请假!
校长同意了王五的请假!