责任链模式(Chain of Responsibility)是一种对象的行为模式。
在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。
请求在这个链上传递,直到链上的某一个对象决定处理此请求。
发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态的重新组织链和分配责任。
责任链可能是一条直线、一个环链或者一个树结构的一部分。
角色如下:
抽象处理者角色(Handler): 定义出一个处理请求的接口。如果需要,接口可以定义出一个方法,以设定和返回对下家的引用。这个角色通常由一个java抽象类或java接口实现。
具体处理者角色(ConcreteHandler): 具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
源码清单:
抽象处理者
public abstract class Handler {
protected Handler successor;
/**
* 处理方法:调用此方法处理请求
*/
public abstract void handleRequest();
/**
* 赋值方法:调用此方法设定下家
* @param successor
*/
public void setSuccessor(Handler successor){
this.successor = successor;
}
/**
* 取值方法
* @return
*/
public Handler getSuccessor(){
return successor;
}
}
具体处理者
public class ConcreteHandler extends Handler {
/**
* 处理方法,调用此方法处理请求
*/
@Override
public void handleRequest() {
if(getSuccessor()!=null){
System.out.println("The request is passed to "+getSuccessor());
getSuccessor().handleRequest();
}else{
System.out.println("The request is handled here.");
}
}
}
客户端
public class Client {
static private Handler handler1,handler2;
public static void main(String[] args) {
handler1 = new ConcreteHandler();
handler2 = new ConcreteHandler();
handler1.setSuccessor(handler2);
handler1.handleRequest();
}
}
可以看出,客户端创建了两个处理者对象,并指定第一个处理者对象的下家是第二个处理者对象,而第二个处理者对象没有下家。然后客户端将请求传递给第一个处理者对象。
这里的这个逻辑很简单:只要有下家,就传递给下家;如果没有下家,就自行处理。
活动时序图
一个纯的责任链模式要求一个具体的处理者对象只能在两个行为中选择一个;
一是承担责任,二是把责任推给下家。不允许出现某一个具体处理者对象在承担了一部分责任后又把责任向下传递。
在一个纯的责任链模式里面,一个请求必须被某一个处理者对象所接收;
在一个不纯的责任链模式里面,一个请求可以最终不被任何接收端对象所接收。
纯的责任链模式的实际例子很难找到,一般看到的例子均是不纯的责任链模式的实现。
1. 系统已经有一个由处理者对象组成的链。这个链可能由合成模式给出。
2. 有多于一个的处理者对象会处理一个请求,而且事先并不知道到底由哪一个处理者对象处理一个请求。这个处理者对象时动态确定的。
3. 系统想发出一个请求给多个处理者对象中的某一个,但是不明显指出是哪一个处理者对象会处理此请求。
4. 处理一个请求的处理者对象集合需要动态的指定时。
责任链模式降低了发出命令的对象和处理命令的对象之间的耦合,它允许多于一个的处理者对象根据自己的逻辑来决定哪一个处理者最终处理这个命令。
链结构的由来
值得指出的是,责任链模式并不创建出责任链。责任链的创建必须由系统的其他部分创建出来。
一个链可以是一条线,一个树,也可以是一个环。链的拓扑结构可以是单连通的或多连通的,责任链模式并不指定责任链的拓扑结构。
如下图,责任链式一个树结构的一部分
命令的传递
在一个责任链上传递的可能不只有一个命令,而是数个命令。