行为型设计模式;收到请求后,链上的每个处理者都可以对请求进行处理,或可以将请求传递给下个处理者。
为什么需要责任链模式
如果不直接使用责任链模式,有下面一个场景:用户在使用一个在线交易系统,目前已经有如下权限控制:只允许认证用户创建订单,管理员可以查看所有订单。
在几个月的开发中,又实现了几个过滤。如防止暴力破解密码,相同的请求缓存等。
问题在于,代码本就臃肿不堪,然后还不断增加新的过滤逻辑。
这也就是责任链模式出现的原因。
像上面的场景,就可以使用责任链,定义清楚需要进行的过滤,每个功能建个相应的类,进行链式处理。
责任链模式的优点
- 单一职责原则。可以对发起操作和执行操作的类进行解耦。
- 开闭原则。可以在不更改现有代码的情况下新增处理者。
源码实现
实现场景:从小明参加某公司的面试开始,某公司的招聘流程就是上面说的 3 轮面试。招聘流程的面试官分别是:第一面是组长老刚,第二面是部门经理老孙,第三面也就是终面是 HR 老刘。为什么说这个场景符合责任链模式呢?首先不管是组长还是部门经理还是 HR,他们都作为面试官,面试官赋予他们的权利是去面试来公司面试的同学,而面试的结果是可传递性的,也就是如果面试通过,就会到下一轮面试,最终成为一条传递链。
@Data @NoArgsConstructor class Interviewee { private String name; private String age; private Boolean teamLeaderOpinion; private Boolean departmentManagerOpinion; private Boolean hrOpinion; } abstract class Interviewer { protected String name; protected Interviewer nextInterviewer; public Interviewer() {} public void setNextInterviewer(Interviewer nextInterviewer) { this.nextInterviewer = nextInterviewer; } public abstract void handleInterview(Interviewee interviewee) throws Exception; } @Data @Slf4j class TeamLeader extends Interviewer { @Override public void handleInterview(Interviewee interviewee) throws Exception { log.info("team leader interviewing!"); interviewee.setTeamLeaderOpinion(new Random().nextBoolean()); if (interviewee.getTeamLeaderOpinion()) { log.info("team leader passed!"); nextInterviewer.handleInterview(interviewee); } else { //抛出定制化错误,这里就直接抛出通用错误了 throw new Exception("组长面试不通过!"); } } } @Data @Slf4j class DepartmentManager extends Interviewer { @Override public void handleInterview(Interviewee interviewee) throws Exception { log.info("department manager interviewing!"); interviewee.setDepartmentManagerOpinion(new Random().nextBoolean()); if (interviewee.getDepartmentManagerOpinion()) { log.info("department manager passed!"); nextInterviewer.handleInterview(interviewee); } else { //抛出定制化错误 throw new Exception("部门主管面试不通过!"); } } } @Data @Slf4j class Hr extends Interviewer { @Override public void handleInterview(Interviewee interviewee) throws Exception { log.info("hr interviewing!"); interviewee.setHrOpinion(new Random().nextBoolean()); if (interviewee.getHrOpinion()) { log.info("hr passed!"); } else { //抛出定制化错误 throw new Exception("HR面试不通过!"); } } } @Test public void interviewChainTest() { int i = 0; while (i < 10) { try { Interviewee interviewee = new Interviewee(); interviewee.setName("面试者"); TeamLeader teamLeader = new TeamLeader(); teamLeader.name = "组长"; DepartmentManager dm = new DepartmentManager(); dm.name = "部门主管"; Hr hr = new Hr(); hr.name = "HR"; teamLeader.setNextInterviewer(dm); dm.setNextInterviewer(hr); teamLeader.handleInterview(interviewee); i++; } catch (Exception e) { log.error("面试不通过", e); } } }
若有收获,就点个赞吧