最近做需求,用到了责任链模式,总结一下。
需求场景:播放器记录着所有的播放行为事件PlayBehaviorEvent,业务方根据回传的播放事件,筛选出满足过滤条件的集合(例如播放进度超过30%)。
此时,为了满足不同业务方的过滤条件,需要设计一个通用的方法,需要业务方把过滤条件给播放器,播放器将集合传给业务方,而过滤条件由业务方自定制。
责任链模式,首先每个条件为一个对象,将所有对象结合成一个链表,并沿着这条链传递事件,直到链上的某一个对象决定处理此事件。
话不多说,看代码好理解。
责任链是啥样的?就是找到链表的头结点
public class InterceptorChain {
private Interceptor mHeader;
public InterceptorChain() {
}
public InterceptorChain add(Interceptor interceptor) {
if (mHeader == null) {
mHeader = interceptor;
} else {
Interceptor header = mHeader;
while (header != null) {
if (header.getNext() == null) {
header.next(interceptor);
break;
}
header = header.getNext();
}
}
return this;
}
public Interceptor getHeader() {
return mHeader;
}
}
再来看看拦截器啥样
public abstract class Interceptor implements IBehaviorInterceptor {
private Interceptor nextInterceptor;
public Interceptor() {
}
/**
*
* @param interceptor 返回nextInterceptor节点
* @return
*/
public Interceptor next(Interceptor interceptor) {
this.nextInterceptor = interceptor;
return nextInterceptor;
}
public Interceptor getNext() {
return nextInterceptor;
}
}
public interface IBehaviorInterceptor {
boolean intercept(PlayBehaviorEvent event);
}
播放器过滤条件:
public synchronized List<PlayBehaviorEvent> getBehaviorRecord(InterceptorChain interceptor) {
if (interceptor == null || interceptor.getHeader() == null) {
// 没有过滤器,就返回了所有事件
return getAll();
}
ArrayList<PlayBehaviorEvent> behaviors = new ArrayList<>();
Interceptor header;
boolean isIntercept;
Map.Entry<String, ArrayList<PlayBehaviorEvent>> entry;
ArrayList<PlayBehaviorEvent> value;
//mEvents就是播放器记录的所有的事件
Iterator<Map.Entry<String, ArrayList<PlayBehaviorEvent>>> entries = mEvents.entrySet().iterator();
while (entries.hasNext()) {
entry = entries.next();
value = entry.getValue();
// 对每一个事件进行遍历
for (PlayBehaviorEvent event : value) {
header = interceptor.getHeader();
// 默认不拦截
isIntercept = false;
// 对所有的拦截条件进行遍历,如果满足所有条件,即都返回false,才能add到返回的集合中
do {
if (header.intercept(event)) {
// 如果有一个为true,即有一个条件不满足,就被拦截
isIntercept = true;
break;
}
header = header.getNext();
} while (header != null);
if (!isIntercept) {
behaviors.add(event);
}
}
}
return behaviors;
}
看业务方如何获取所有满足条件的集合
拦截链表中有多个拦截方法,必须满足所有条件,才不拦截
List<PlayBehaviorEvent> eventList = playerApi.getBehaviorRecord(new InterceptorChain()
.add(new Interceptor() {
@Override
public boolean intercept(PlayBehaviorEvent event) {
if (条件1) {
// 满足条件1,不拦截
return false;
}
return true;
}
})
.add(new Interceptor() {
@Override
public boolean intercept(PlayBehaviorEvent event) {
if (条件2) {
// 满足条件2,不拦截
return false;
}
return true;
}
}));