本文最后更新于:2022年7月13日 下午
概览 :责任链模式
责任链模式 将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求,如果能则处理,如果不能则传递给链上的下一个对象处理。
使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系,将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理他为止。
参考链接:Java设计模式13:责任链模式 - 五月的仓颉 - 博客园 (cnblogs.com)
Java责任链模式(Chain of responsibility) - 腾讯云开发者社区-腾讯云 (tencent.com)
案例:洗脸、吃饭、学习 学习之前要洗脸和吃饭等动作,完成之后才进行学习,普通编程如何处理呢?
直接先执行洗脸和吃饭任务,然后再学习
问题:新增任务或者修改顺序比较复杂 ,违反开闭原则 。
责任链优化:
任务列表:
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 35 36 37 38 39 40 41 42 43 44 45 46 47 public class PreparationList { private boolean washFace; private boolean washHair; private boolean haveBreakfast; public boolean isWashFace () { return washFace; } public void setWashFace (boolean washFace) { this .washFace = washFace; } public boolean isWashHair () { return washHair; } public void setWashHair (boolean washHair) { this .washHair = washHair; } public boolean isHaveBreakfast () { return haveBreakfast; } public void setHaveBreakfast (boolean haveBreakfast) { this .haveBreakfast = haveBreakfast; } @Override public String toString () { return "ThingList [washFace=" + washFace + ", washHair=" + washHair + ", haveBreakfast=" + haveBreakfast + "]" ; } }
抽象类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public abstract class AbstractPrepareFilter { private AbstractPrepareFilter nextPrepareFilter; public AbstractPrepareFilter (AbstractPrepareFilter nextPrepareFilter) { this .nextPrepareFilter = nextPrepareFilter; } public void doFilter (PreparationList preparationList, Study study) { prepare(preparationList); if (nextPrepareFilter == null ){ study.study(); }else { nextPrepareFilter.doFilter(preparationList,study); } } public abstract void prepare (PreparationList preparationList) ; }
洗脸行为:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class WashFacePrepareFilter extends AbstractPrepareFilter { public WashFacePrepareFilter (AbstractPrepareFilter nextPrepareFilter) { super (nextPrepareFilter); } @Override public void prepare (PreparationList preparationList) { if (preparationList.isWashFace()) { System.out.println("洗脸" ); } } }
吃饭行为:
1 2 3 4 5 6 7 8 9 10 11 12 13 public class EatFoodPrepareFilter extends AbstractPrepareFilter { public EatFoodPrepareFilter (AbstractPrepareFilter nextPrepareFilter) { super (nextPrepareFilter); } @Override public void prepare (PreparationList preparationList) { if (preparationList.isHaveBreakfast()) { System.out.println("吃早餐" ); } } }
客户端调用
1 2 3 4 5 6 7 8 9 10 11 12 public static void main (String[] args) throws Exception { PreparationList preparationList = new PreparationList(); preparationList.setWashFace(true ); preparationList.setHaveBreakfast(true ); Study study = new Study(); AbstractPrepareFilter haveBreakfastFilter = new EatFoodPrepareFilter(null ); AbstractPrepareFilter washFaceFilter = new WashFacePrepareFilter(haveBreakfastFilter); washFaceFilter.doFilter(preparationList, study); }
问题:
对于客户端来说,行为串起来的模式都需要考虑。
案例优化 新建接口
1 2 3 public interface StudyPrepareFilter { public void doFilter (PreparationList preparationList, FilterChain filterChain) ; }
新建责任链: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 public class FilterChain implements StudyPrepareFilter { private int pos = 0 ; private Study study; private List<StudyPrepareFilter> studyPrepareFilterList; public FilterChain (Study study) { this .study = study; } public void addFilter (StudyPrepareFilter studyPrepareFilter) { if (studyPrepareFilterList == null ) { studyPrepareFilterList = new ArrayList<StudyPrepareFilter>(); } studyPrepareFilterList.add(studyPrepareFilter); } @Override public void doFilter (PreparationList thingList, FilterChain filterChain) { if (pos == studyPrepareFilterList.size()) { study.study(); }else { studyPrepareFilterList.get(pos++).doFilter(thingList, filterChain); } } }
实现洗发
1 2 3 4 5 6 7 8 9 10 11 public class WashHairFilter implements StudyPrepareFilter { @Override public void doFilter (PreparationList preparationList, FilterChain filterChain) { if (preparationList.isWashHair()) { System.out.println("洗完头发" ); } filterChain.doFilter(preparationList, filterChain); } }
实现吃早餐
1 2 3 4 5 6 7 8 9 10 11 public class HaveBreakfastFilter implements StudyPrepareFilter { @Override public void doFilter (PreparationList preparationList, FilterChain filterChain) { if (preparationList.isHaveBreakfast()) { System.out.println("吃完早饭" ); } filterChain.doFilter(preparationList, filterChain); } }
客户端调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public static void main (String[] args) throws Exception { PreparationList preparationList = new PreparationList(); preparationList.setWashHair(true ); preparationList.setHaveBreakfast(true ); Study study = new Study(); StudyPrepareFilter washHairFilter = new WashHairFilter(); StudyPrepareFilter haveBreakfastFilter = new HaveBreakfastFilter(); FilterChain filterChain = new FilterChain(study); filterChain.addFilter(washHairFilter); filterChain.addFilter(haveBreakfastFilter); filterChain.doFilter(preparationList, filterChain); }
FilterChain可以作为spring bean来注入。
核心概览:
FilterChain
表示责任链,内部有一个list对象来存储各个filter
,list的先后顺序就是执行的先后顺序。
结合Spring来使用 自定义排序注解
1 2 3 4 5 6 7 8 9 10 11 12 import org.springframework.core.Ordered;@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented public @interface FilterOrder { int value () default Ordered.LOWEST_PRECEDENCE ; }
任务列表增加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Service public class FilterChain implements InitializingBean { @Resource private List<Filter> filterList; public void doFilter (BanCallBackContext context) { for (Filter filter : filterList) { if (!filter.do (context)) { return ; } } } @Override public void afterPropertiesSet () { filterList = filterList.stream() .sorted(Comparator.comparingInt(filter -> filter.getClass().getAnnotation(FilterOrder.class).value()) .thenComparing(filter -> filter.getClass().getSimpleName())) .collect(Collectors.toList()); } }