Java 设计模式之责任链模式
一、定义
为了避免请求发送者与多个请求处理者耦合在一起,于是将所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链;当有请求发生时,可将请求沿着这条链传递,直到有对象处理它为止。
主要角色:
**抽象处理者: **定义一个处理请求的接口,包含抽象处理方法和一个后继连接。
**具体处理者: **实现抽象处理者的处理方法,判断能否处理本次请求,如果可以处理则处理,否则将该请求转给它的后继者。
客户端:创建处理链,并向链头的具体处理者对象提交请求,他不关心处理细节和请求的传递过程。
二、代码实现
举例:例如员工请假,请假一天需要组长审批,请假三天需要经理审批,请假七天需要老板审批,每个角色可以审批的天数不同,当无权限审批时则转给上级领导。
抽象处理者:领导类
public abstract class Leader { private Leader nextLeader; public Leader getNextLeader() { return nextLeader; } public void setNextLeader(Leader nextLeader) { this.nextLeader = nextLeader; } public abstract void handlerRequest(); }
具体处理者:组长类
public class GroupLeader extends Leader{ @Override public void handlerRequest(int days) { if (days==1){ System.out.println("组长批准了请假:"+days+"天"); }else { if (getNextLeader()!=null){ getNextLeader().handlerRequest(days); } } } }
具体处理者:经理类
public class Manager extends Leader{ @Override public void handlerRequest(int days) { if (days<=3){ System.out.println("经理批准了请假:"+days+"天"); }else { if (getNextLeader()!=null){ getNextLeader().handlerRequest(days); } } } }
具体处理者:老板
public class Boss extends Leader{ @Override public void handlerRequest(int days) { if (days<=7){ System.out.println("老板批准了请假:"+days+"天"); }else { if (getNextLeader()!=null){ getNextLeader().handlerRequest(days); }else { System.out.println("请假天数太多 不予审批"); } } } }
使用:
public static void main(String[] args) { //组装责任链 GroupLeader groupLeader = new GroupLeader(); Manager manager = new Manager(); Boss boss = new Boss(); groupLeader.setNextLeader(manager); manager.setNextLeader(boss); //发送请求 groupLeader.handlerRequest(1); groupLeader.handlerRequest(2); groupLeader.handlerRequest(5); }
输出:
组长批准了请假:1天 经理批准了请假:2天 老板批准了请假:5天
这里分别请假1,2,5天,可以看到请假不同的天数,是由不同审批权限的处理者来处理的。
三、总结
优点:
降低了对象之间的耦合度。
增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。
缺点:
不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
职责链建立的合理性要靠客户端来保证,增加了客户端的复杂性,可能会由于职责链的错误设置而导致系统出错,如可能会造成循环调用。
使用场景:
多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
可动态指定一组对象处理请求,或添加新的处理者。
需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。