如果不使用责任链,则client要知道有多少个handler、什么情况调用什么handler,client与handler耦合。
对handler变动、阀值调整,都需要调整client。
违反开闭原则。
1.client:调用者,发出消息。
2.handler interface:接口,同时持有同类的1个对象。
3.concrete handler:
1.client:调用者,发出消息。
2.handler interface:接口,增加handlerChain参数。
3.concrete handler:
4.**handlerChain:重要。1)是handler的实现;2)维护chain;3)递归调用
![在这里插入图片描述](https://img-blog.csdnimg.cn/5bf6a1adeaf642ac9d7e31d99a1bd02a.png
以下场景适合责任链:
1.当有多个handler可以处理消息时。
2.handler不可提前知道。
3.handler需要自动确定时。
4.请求发给一组对象,但不许指定接受者。
1.采购审批:开闭
2.GUI事件传播:控件事件传播给自身控件和其他响应控件。
3.订单快递系统:最终完成取决于价格、大小、物流类型、目标等其他因素;并且随着特定场景的出现,会随时更新改部分逻辑。
–链条拼接
&:如果是遍历型的,不可以直接拼接,需要拼接的chain也实现doFilter;
如果是链表型的,可以拼接,因为拼接的链表对外暴露的也是第1个节点的filter;
如果是"复杂型"的,可以了拼接,因为chain也是Filter的实现。
ps:拼接的关键是链表也要实现Filter。
–任意链条判断是否继续
&:节点中判定是否调用下一节点。
–按顺序执行链条
&:都可以。
–模拟servlet里的责任链?1个过滤器,同时处理request、response;
&:消息被拆分成了2个,request、response;request按1、2、3处理;response按3、2、1处理。
因为:代码结构是:处理request–>责任链调用(递归)–>处理response;
责任链调用会持续一层层调用,直到最深层返回后,再一层层执行。
/*
* 过滤器接口
* */
public interface StudyPrepareFilter {
/*
* 与【简单】doFilter方法对比,增加了FilterChain参数。
* preparationList是消息。
* */
public void doFilter(PreparationList preparationList, FilterChain filterChain);
}
/*
* FilterChain:维护了Filter列表。
* 也要实现Filter接口和doFilter方法,
* */
public class FilterChain implements StudyPrepareFilter {
// chain标志位
private int pos = 0;
private Study study;
private List<StudyPrepareFilter> filters;
public FilterChain(Study study) {
this.study = study;
}
public void addFilter(StudyPrepareFilter filter) {
if (filters == null) {
filters = new ArrayList<StudyPrepareFilter>();
}
filters.add(filter);
}
/*preparationList:消息,会一直传递
* filterChain:自己调用自己,驱动chain上的filter都得到执行
* */
@Override
public void doFilter(PreparationList preparationList, FilterChain filterChain) {
if (pos == filters.size()) {
// pos标记到链尾,终结,执行最终任务
study.study();
return;
}
// chain移位,
// 执行下一个filter,
// 继续传入:msg和filterchain自己
// 在chain节点filter内部,
filters.get(pos++).doFilter(preparationList,filterChain);
}
}
/* 具体的3个handler */
public class HaveBreakfast implements StudyPrepareFilter{
@Override
public void doFilter(PreparationList preparationList, FilterChain filterChain) {
if (preparationList.isWashFace()) {
System.out.println("do haveBreakfast()");
}
// 继续传递消息、filterChain(自己);自己
filterChain.doFilter(preparationList,filterChain);
System.out.println("do haveBreakfast()--done");
}
}
public class WashFace implements StudyPrepareFilter{
@Override
public void doFilter(PreparationList preparationList, FilterChain filterChain) {
if (preparationList.isWashFace()) {
System.out.println("do washFace()");
}
// 继续传递消息、filterChain(自己);自己
filterChain.doFilter(preparationList,filterChain);
System.out.println("do washFace()--done");
}
}
public class WashHair implements StudyPrepareFilter{
@Override
public void doFilter(PreparationList preparationList, FilterChain filterChain) {
if (preparationList.isWashFace()) {
System.out.println("do washHair()");
}
// 继续传递消息、filterChain(自己);自己
filterChain.doFilter(preparationList,filterChain);
System.out.println("do washHair()--done");
}
}
public class chainOfResponsibility {
public static void main(String[] args) {
FilterChain filterChain = new FilterChain(new Study());
filterChain.addFilter(new WashFace());
filterChain.addFilter(new WashHair());
filterChain.addFilter(new HaveBreakfast());
PreparationList msg = new PreparationList();
msg.setHaveBreakfast(true);
msg.setWashFace(true);
msg.setWashHair(true);
// filterChain.doFilter(msg,filterChain);
System.out.println("========责任链拼接========");
FilterChain filterChain2 = new FilterChain(new Study());
filterChain2.addFilter(new WashFace());
filterChain2.addFilter(new WashHair());
filterChain.addFilter(filterChain2);
filterChain.doFilter(msg,filterChain);
}
}
https://www.oodesign.com/chain-of-responsibility-pattern
https://www.freesion.com/article/67401039033/