责任链模式
定义:将能够处理同一类请求的对象练成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象。
角色:
1)抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个Java抽象类或者Java接口实现。上图中Handler类的聚合关系给出了具体子类对下家的引用,抽象方法handleRequest()规范了子类处理请求的操作。
2)具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
3)客户类(Client)角色:创建处理链,并向链头的具体处理者对象提交请求,它不关心处理细节和请求的传递过程。
图示:
package com.offcn.designpattern.chainOfResppattren; public class ChainOfRespDemo { public static void main(String[] args) { Leader a = new Director("王主任"); Leader b = new Manager("李经理"); Leader c = new GeneralManager("张总经理"); //设置关系 a.setNextLeader(b); b.setNextLeader(c); LeaveRequest leaveRequest = new LeaveRequest("岁岁",14,"串休"); a.handleRequest(leaveRequest); } } //抽象类,领导者 abstract class Leader{ protected String name; protected Leader nextLeader; public Leader(String name) { this.name = name; } public void setNextLeader(Leader nextLeader){ this.nextLeader = nextLeader; } //核心的业务方法 public abstract void handleRequest(LeaveRequest leaveRequest); } //主任 class Director extends Leader{ public Director(String name) { super(name); } @Override public void handleRequest(LeaveRequest leaveRequest) { if(leaveRequest.getLeaveDays() < 3){ System.out.println("员工"+leaveRequest.getEmpName()+"请假"+leaveRequest.getLeaveDays()+",请假原因:"+leaveRequest.getReason()); System.out.println(name + "审批"); }else{ this.nextLeader.handleRequest(leaveRequest); } } } //总经理 class GeneralManager extends Leader{ public GeneralManager(String name) { super(name); } @Override public void handleRequest(LeaveRequest leaveRequest) { if(leaveRequest.getLeaveDays() < 30){ System.out.println("员工"+leaveRequest.getEmpName()+"请假"+leaveRequest.getLeaveDays()+",请假原因:"+leaveRequest.getReason()); System.out.println(name + "审批"); }else{ System.out.println("员工"+leaveRequest.getEmpName()+"请假"+leaveRequest.getLeaveDays()+",是不想干了吗!!!"); } } } //经理 class Manager extends Leader{ public Manager(String name) { super(name); } @Override public void handleRequest(LeaveRequest leaveRequest) { if(leaveRequest.getLeaveDays() < 10){ System.out.println("员工"+leaveRequest.getEmpName()+"请假"+leaveRequest.getLeaveDays()+",请假原因:"+leaveRequest.getReason()); System.out.println(name + "审批"); }else{ this.nextLeader.handleRequest(leaveRequest); } } } //离职者基本信息 class LeaveRequest{ private String empName; private int leaveDays; private String reason; public LeaveRequest(String empName, int leaveDays, String reason) { this.empName = empName; this.leaveDays = leaveDays; this.reason = reason; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public int getLeaveDays() { return leaveDays; } public void setLeaveDays(int leaveDays) { this.leaveDays = leaveDays; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } }
输出:
优点:
1)降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
2)增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
3)增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
4)责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
5)责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
1)不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
2)对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
3)职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
场景:
1) 公司中公文审批
2) Java中异常机制就是责任链模式,一个try可以对应多个catch,当第一个catch不匹配类型,则自动跳到第二个catch
3) Servlet开发中,过滤器的链式处理
4) Struts2中,拦截器的调用也是典型的责任链模式。
扩展:
职责链模式存在以下两种情况。
1)纯的职责链模式:一个请求必须被某一个处理者对象所接收,且一个具体处理者对某个请求的处理只能采用以下两种行为之一:自己处理(承担责任);把责任推给下家处理。
2)不纯的职责链模式:允许出现某一个具体处理者对象在承担了请求的一部分责任后又将剩余的责任传给下家的情况,且一个请求可以最终不被任何接收端对象所接收。
非链表方式实现责任链:
通过集合,数组生成责任链更加实用,因为具体的Handler大部分都是外部单位追加的,链表方式定义责任链会比较困难。
原文:https://www.cnblogs.com/bai3535/p/12323434.html