概述
- 意图:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止
- 适用场景:
- 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定
- 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
- 处理一个请求的对象集合应被动态指定
实现
请假问题是一个经典的责任链,假设请假不超过3天,老师可以批准,超过3天只能主任批准
// 责任链抽象类
public abstract class Handler {
private Handler nextHandler;
public Handler getNextHandler() {
return nextHandler;
}
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
public abstract void handle(int day);
}
// 老师,可以批准不超过3天的请假
class Teacher extends Handler {
@Override
public void handle(int day) {
if(day <= 3) {
System.out.println("老师已经批准请假,天数:" + day);
} else {
Handler h = getNextHandler();
h.handle(day);
}
}
}
// 主任,可以批注超过3天的请假
class Registrar extends Handler {
@Override
public void handle(int day) {
if(day > 3) {
System.out.println("主任已经批准请假,天数:" + day);
} else {
Handler h = getNextHandler();
h.handle(day);
}
}
}
// 客户端
public class Client {
public static void main(String[] args) throws Exception {
Handler h1 = new Teacher();
Handler h2 = new Registrar();
h1.setNextHandler(h2);
h1.handle(3);
h1.handle(10);
}
}
输出结果
老师已经批准请假,天数:3
主任已经批准请假,天数:10
实际应用
java.lang.ClassLoader#load()
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
// 若自己无法加载则委托给父loader
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}