引子
假定我们设想某一个场景,在一个工厂里我们需要经过一系列的工序要生产加工产品。这些生产工序在工厂中我们一般称之为流水线。这些流水线有一个比较有意思的特性,就是每一个步骤是针对生产过程中某一个方面起作用,比如对产品的锻造、抛光,包装等。同时他们所进行的所有行为都是围绕着同一个产品,有严格的顺序要求。做完某一步之后就接着到下一步。
模式的基本概念
前面的工厂流水线可以作为chain of responsibility模式的一个类比。和流水线类似,在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。发出这个请求的客户端并不知道链上的哪一个对象最终处理这个请求,这使得系统可以在不影响客户端的情况下动态地重新组织链和分配责任。
该模式的结构图如下:
从图中我们可以看到,我们定义的抽象基类Handler包含有一个指向自身类型的引用。而具体的实现ConcreteHandler1, ConcreteHandler2等可以针对不同的方面做具体的处理实现,这些实现类在处理完该方面之后再将请求转发给下一个。由于successor的引用,我们可以构成一个链表类型的结构,将所有的具体实现类给串起来。
一个参考实现
在实际的实现和应用中,可能会有几种选项我们可以考虑。一个是可以将请求传递整个责任链条,在每个处理节点handler上面选择自己能否处理,否则就传递给下一个。这相当于实际上只有一个handler真正处理了,其他的都是传递的。碰到真正处理的就已经返回了。另外,也可以若干个handler每个都处理一部分,然后直到某个节点处理完毕返回。这些情况都可以。假定我们选择地一种情况。
对应的代码分别如下:
Handler: 一方面定义了一个链表结构的基础,同时也作为一个抽象的基类给具体子类来实现。
public abstract class Handler
{
// Fields
protected Handler successor;
// Methods
public void setSuccessor( Handler successor )
{
this.successor = successor;
}
public abstract void handleRequest( int request );
}
ConcreteHandler1, ConcreHandler2分别作为两个具体的Handler子类实现:
// "ConcreteHandler1"
public class ConcreteHandler1 extends Handler
{
// Methods
override public void handleRequest( int request )
{
// if match the handle condition...
else
if( successor != null )
successor.HandleRequest( request );
}
}
// "ConcreteHandler2"
public class ConcreteHandler2 extends Handler
{
// Methods
override public void handleRequest( int request )
{
// if match the handle condition...
else
if( successor != null )
successor.handleRequest( request );
}
}
在具体调用整个责任链的时候,我们可以使用如下的代码:
// Setup Chain of Responsibility
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
h1.setHandler(h2);
h1.handleRequest(3);
我们可以看到,在代码中,我们手工构建一个链表,然后调用handleRequest方法。从表面上看就是h1执行了handleRequest方法,实际上根据需要可能会有h1将请求传递到后面的h2。这就是传递中最核心的部分。
和其他模式的对比
和observer pattern的比较
如果我们和observer pattern的思路进行比较,会发现他们在一定程度上有很大的相似性。下图是observer pattern的类结构图。
经过比较,我们会发现。chain of responsibility模式里面所有的handler都有一个指向后面的引用,形成了一个链表的样式。通过一个接一个的传递来处理请求。而observer pattern里所有注册的观察者也可以通过一个list,也可以是链表的方式来得到通知。在observer pattern相当于将process这个处理的方法抽象成一个独立的接口,而且一般将所有注册链的过程封装在抽象基类里。而在chain of responsibility里会手工来构造这个处理链。这里像一个工厂的流水线,强调流程以及顺序。每一个handler相当于其中的某一道加工工序,这样就不能允许出现顺序错乱。所以该模式比较强调一个比较灵活的强调顺序的过程。
另外一方面,chain of responsibility允许所有的handler都有机会来处理请求,但不一定要所有的handler都来处理,在具体的handler可能只是起到一个转发的作用。而observer patter中所有的观察者都相当于一个关注者,他们当事件触发的时候相当于所有人都有动作,而不是有的有而有的没有。不存在前面一个传递到后面一个的概念。而observer pattern强调一个对事件通知的分离,并不强调观察者行动的顺序性。只要所有注册的观察者被通知到就可以了,至于谁先被通知,谁后被通知都无所谓。
和template method的比较
template method模式和它也有很多相似的地方。下面是template method模式的结构图。
template method模式也强调一个过程,一般会是在抽象基类里定义好了一个过程需要的步骤。每个步骤对应一个方法,具体方法的实现依赖于实现的子类。和chain of responsibility模式比起来,这个模式里定义的过程是固定的,如果需要调整的话就要调整基类里的方法。而在chain of responsibility模式中handler是可以根据需要组合的,相对来说更加有灵活性。
总结
chain of responsibility模式本身比较简单,就相当于抽象出一个处理的接口然后用构造链表的方式来把各具体的处理步骤串联起来。在实际应用中可能包括有单个处理并返回或者多个处理返回的情况。一些典型的应用包括MINA里面Filter chain实现,就用到了该模式并采用了第二种方式。而另外一个在Apache commons chain的开源实现中,它采用了第一种方式。这些具体实现会在后面一篇文章中详细分析。