职责链模式的定义
职责链模式(Chain of Responsibility Pattern)的定义为:避免请求发送者与接受者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式又称为责任链模式,它是一种对象行为型模式。
职责链模式的结构图
职责链模式主要包含下边几个角色:
1、Handler(抽象处理者)
抽象处理者定义了一个处理请求的接口,它一般设计为抽象类,由于不同的具体处理者处理请求的方式不同,因此在其中定义了抽象请求处理方法。因为每一个处理者的下家还是一个处理者,因此在抽象处理者中定义了一个自类型(抽象处理者类型)的对象,作为其对下家的应用。
2、ConcreteHandler(具体处理者)
具体处理者是抽象处理者的子类,它可以处理用户请求,在具体处理者类中实现了抽象处理者中定义的抽象请求处理方法,在处理请求之前需要进行判断,看是否有相应的处理权限,如果可以处理请求就处理它,否则将请求转发给后继者,在具体处理者中可以访问链中下一个对象,以便请求的转发。
职责链模式的实例
日常生活中的请假流程与职责链模式十分相像,我们来实现这个请假流程。
简单说明一下下边的实例:员工请假天数小于3天可以由主任审批,大于等于3天且小于10天由经理审批,大于等于10天且小于30天由总经理审批,大于30天则拒绝审批。下边的实例中,为了方便看懂整个流程,我将请假条也进行抽象封装。
请假条类LeaveRequest(非职责链模式核心)
public class LeaveRequest {
private String leaveName;
private int leaveDays;
public LeaveRequest(String leaveName, int leaveDays) {
super();
this.leaveName = leaveName;
this.leaveDays = leaveDays;
}
public String getLeaveName() {
return leaveName;
}
public void setLeaveName(String leaveName) {
this.leaveName = leaveName;
}
public int getLeaveDays() {
return leaveDays;
}
public void setLeaveDays(int leaveDays) {
this.leaveDays = leaveDays;
}
}
抽象处理者类Leader
public abstract class Leader {
protected String name;
protected Leader successor;
public void setSuccessor(Leader successor) {
this.successor = successor;
}
public Leader(String name) {
super();
this.name = name;
}
public abstract void handleRequest(LeaveRequest request);
}
具体处理者类
Director(主任)GeneralManager(总经理)
public class Director extends Leader{
public Director(String name){
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays()<3){
System.out.println("主任"+ name + "审批员工" + request.getLeaveName() + "的请假条,请假天数为" + request.getLeaveDays());
}
else{
if(this.successor != null)
this.successor.handleRequest(request);
}
}
}
Manager(经理)
public class Manager extends Leader{
public Manager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays()<10){
System.out.println("经理"+ name + "审批员工" + request.getLeaveName() + "的请假条,请假天数为" + request.getLeaveDays());
}
else{
if(this.successor != null)
this.successor.handleRequest(request);
}
}
}
GeneralManager(总经理)
public class GeneralManager extends Leader{
public GeneralManager(String name) {
super(name);
}
@Override
public void handleRequest(LeaveRequest request) {
if(request.getLeaveDays()<30){
System.out.println("总经理"+ name + "审批员工" + request.getLeaveName() + "的请假条,请假天数为" + request.getLeaveDays());
}
else{
System.out.println("想请假"+request.getLeaveDays()+"天是不可能的,除非"+request.getLeaveName()+"想辞职");
}
}
}
测试类Client
public class Client {
public static void main(String[] args) {
Leader objDirector,objManager,objGeneralManager;
objDirector = new Director("太白金星");
objManager = new Manager("玉皇大帝");
objGeneralManager = new GeneralManager("如来佛祖");
objDirector.setSuccessor(objManager);
objManager.setSuccessor(objGeneralManager);
LeaveRequest lr1 = new LeaveRequest("太乙真人", 2);
objDirector.handleRequest(lr1);
LeaveRequest lr2 = new LeaveRequest("哮天犬", 5);
objDirector.handleRequest(lr2);
LeaveRequest lr3 = new LeaveRequest("天蓬元帅", 15);
objDirector.handleRequest(lr3);
LeaveRequest lr4 = new LeaveRequest("二郎神",50 );
objDirector.handleRequest(lr4);
}
}
测试结果
职责链模式的优缺点
优点
- 职责链模式降低了请求发送者和接收者的耦合关系
- 简化对象之间的相互连接,请求处理对象只需要位置一个指向其后继者的引用,而不用维持它对所有的候选处理者的引用。
- 系统容易扩展,在系统中增加一个新的具体请求处理者无须修改原来系统的代码,只需要在客户端重写建立责任链就行,从这点看是符合开闭原则的。
缺点
- 不能保证请求一定能被接收到,一个请求没有明确的接收者,就无法保证它一定能被处理,有可能到链尾都无法被处理。
- 如果职责链过长,请求的过程会十分耗时,且一旦出现环链,那么可能造成死循环。
职责链模式的应用
职责链模式其实在实际开发过程中使用的挺多的,SpringAOP、JVM的双亲委派机制等等,Java中的异常处理机制也类似一种职责链模式。