设计模式之责任链模式

责任链模式的定义

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

标准的责任链模式,个人总结下来有如下几个特点:

  • 链上的每个对象都有机会处理请求
  • 链上的每个对象都持有下一个要处理对象的引用
  • 链上的某个对象无法处理当前请求,那么它会把相同的请求传给下一个对象

用一张图表示以下使用了责任链模式之后的架构:

也就是说,责任链模式满足了请求发送者与请求处理者之间的松耦合,抽象非核心的部分,以链式调用的方式对请求对象进行处理

责任链模式的优点及使用场景

  • 实现了请求发送者与请求处理者之间的松耦合
  • 可动态添加责任对象、删除责任对象、改变责任对象顺序,非常灵活
  • 每个责任对象专注于做自己的事情,职责明确

什么时候需要用责任链模式?

系统设计的时候,注意区分主次就好,即哪部分是核心流程,哪部分是辅助流程,辅助流程是否有N多if...if...if...的场景,如果是且每个if都有一个统一的抽象,那么抽象辅助流程,把每个if作为一个责任对象进行链式调用,优雅实现,易复用可扩展。

首先还是抽象一个Filter:

 public interface StudyPrepareFilter {
     public void doFilter(PreparationList preparationList, FilterChain filterChain);
    }

注意这里多了一个FilterChain,也就是责任链,是用于串起所有的责任对象的,它也是StudyPrepareFilter的一个子类:

public class FilterChain implements StudyPrepareFilter {

    private int pos = 0;

    private Study study;

    private List studyPrepareFilterList;

    public FilterChain(Study study) {
        this.study = study;
    }

    public void addFilter(StudyPrepareFilter studyPrepareFilter) {
        if (studyPrepareFilterList == null) {
            studyPrepareFilterList = new ArrayList();
        }

        studyPrepareFilterList.add(studyPrepareFilter);
    }

    @Override
    public void doFilter(PreparationList thingList, FilterChain filterChain) {
        // 所有过滤器执行完毕
        if (pos == studyPrepareFilterList.size()) {
            study.study();
        }

        studyPrepareFilterList.get(pos++).doFilter(thingList, filterChain);
    }
}

即这里有一个计数器,假设所有的StudyPrepareFilter没有调用完毕,那么调用下一个,否则执行Study的study()方法,即责任链调用完毕。


洗头
public class WashHairFilter implements StudyPrepareFilter {
    @Override
    public void doFilter(PreparationList preparationList, FilterChain filterChain) {
        if (preparationList.isWashHair()) {
            System.out.println("洗完头发");
        }

        filterChain.doFilter(preparationList, filterChain);
    }
}

//洗脸
public class WashFaceFilter implements StudyPrepareFilter {

    @Override
    public void doFilter(PreparationList preparationList, FilterChain filterChain) {
        if (preparationList.isWashFace()) {
            System.out.println("洗完脸");
        }
        filterChain.doFilter(preparationList, filterChain);
    }
}


//吃饭
public class HaveBreakfastFilter implements StudyPrepareFilter {

    @Override
    public void doFilter(PreparationList preparationList, FilterChain filterChain) {
        if (preparationList.isHaveBreakfast()) {
            System.out.println("吃完早饭");
        }

        filterChain.doFilter(preparationList, filterChain);
    }
}

调用方法

@Test
public void testResponsibilityAdvance() {
    PreparationList preparationList = new PreparationList();
    preparationList.setWashFace(true);
    preparationList.setWashHair(false);
    preparationList.setHaveBreakfast(true);

    Study study = new Study();

    StudyPrepareFilter washFaceFilter = new WashFaceFilter();
    StudyPrepareFilter washHairFilter = new WashHairFilter();
    StudyPrepareFilter haveBreakfastFilter = new HaveBreakfastFilter();

    FilterChain filterChain = new FilterChain(study);
    filterChain.addFilter(washFaceFilter);
    filterChain.addFilter(washHairFilter);
    filterChain.addFilter(haveBreakfastFilter);

    filterChain.doFilter(preparationList, filterChain);
}

有的人可能会问,你这个增加、减少责任对象,testResponsibilityAdvance()方法,不是还得addFilter,或者删除一行吗?我们回想一下,Servlet我们增加或减少Filter需要改动什么代码吗?不用,我们需要改动的只是web.xml而已。同样的道理,FilterChain里面有studyPrepareFilterList,我们完全可以把FilterChain做成一个Spring Bean,所有的Filter具体实现类也都是Spring Bean,注入studyPrepareFilterList就好了,伪代码为:


    
        
            
            
            
        
    

可以反转顺序执行的责任链

下面的代码是一个责任链实现方式,类似于servlet里面的filter实现。对于request和response的顺序做了反转。即:request是123的执行顺序,response是321的执行顺序。

/**
 * 责任链模式
  */
public class Filter_Test {
    public static void main(String[] a) {
        Request request = new Request();
        request.str = "大家好,
                    
                    

你可能感兴趣的:(设计模式之责任链模式)