责任链模式的使用

责任链模式(Chain of Responsiblity)

定义: 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
结构实图:

责任链模式涉及角色如下:

* 待处理(Client)角色:一个需要处理的请求,可以是消息或者其他
* 抽象处理者(Handler)角色:定义一个对外处理请求的接口。由它将请求分发到具体处理者( ConcreteHandler)角色进行逐次请求处理。抽象处理者(Handler)角色和具体处理者(ConcreteHandler)角色是聚合关系
* 具体处理者(ConcreteHandler)角色:具体处理者接受到请求时,对其感兴趣的消息处理,或者传递给下个具体处理者处理

SMP中责任链模式的运用

接口定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface Filter {

public void messageReceived(String msgType,List<String> contents,NextFliter nextFliter);

public static interface NextFliter{

void doFilter(String msgType,List<String> contents);

}

public static interface FilterChain{
public void addFirst(Filter filter);
public void addLast(Filter filter);
public void messageReceived(String msgType, List<String> contents);
}

}

接口详细说明:

  • Filter接口:

    对应责任链模式中的就是具体处理者(ConcreteHandler)角色,只有一个方法messageReceived(String msgType,List contents,NextFliter nextFliter). 其中msgType和contents就是需要处理的请求消息,对应责任链中的待处理(Client)角色。nextFliter是调用下一个具体处理(ConcreteHandler)角色,这样做的好处就是Filter不必只有下一个Filter的引用。具体如何实现见下面的FilterChain的实现

  • FilterChain接口:

    对应责任链模式中的抽象处理(Handler)者角色。该接口持有所有的Filter,addFirst(Filter filter)和addLast(Filter filter)方法就是向FilterChain中加入具体处理者(ConcreteHandler)角色。当请求消息到来时,FilterChain调用自身的messageReceived方法,将请求传给第一个Filter,Filter再通过自己的messageReceived方法对请求处理或者传递给下一个Filter

  • NextFliter接口:

    从字面意思即下一个Filter,但这个接口同样由FilterChain实现,此接口主要是通知FilterChain获取下一个Filter处理请求消息

FilterChain具体实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class DefaultFilterChain implements Filter.NextFliter,Filter.FilterChain {
private LinkedList<Filter> fliters = new LinkedList<Filter>();
private int index = 0;

public DefaultFilterChain(){}

public void addLast(Filter fliter) {
if (fliter == null)
return;
fliters.addLast(fliter);
}

public void addFirst(Filter fliter) {
if (fliter == null)
return;
fliters.addFirst(fliter);
}


public void messageReceived(String msgType, List<String> contents) {
index = -1;
doFilter(msgType, contents);
}



public void doFilter(String msgType, List<String> contents) {
index++;
if( index < fliters.size()){
fliters.get( index).messageReceived(msgType, contents, this);
}
}

}

FilterChain实现总结:
优点

1. Filters使用链表存储,实现简单。每个Filter不必引用下一个Filter,由FilterChain实现,这样Filter实现比较简单方便
2. FilterChain同时实现NextFliter,每个Filter在调用下一个Filter时只需要调用nextFilter.doFilter(...)方法,这样做实现了接口隔离的效果

不足

1. 内部使用index,造成线程不安全,如果对messageReceived方法同步代价太高,不合适
2. 虽然FilterChain和NextFilter起到接口隔离效果,但两个接口同时由DefaultFilterChain实现,代码耦合度太高,不利于拓展
3. 对请求消息不够抽象,造成功能单一
4. 只能单向过滤处理消息,不能反向

优化空间

1. 不使用LinkedList,自己实现单向链表或者双向链表,避免使用index实现线程安全
2. 使用双向链表实现双向过滤处理,既可以处理messageReceived消息,又可以处理messageSent消息
3. FilterChain和NextFilter分开实现,降低耦合度

有机会介绍下在Mina中责任链是如何实现的…