设计模式之责任链模式

2020-06-26  本文已影响0人  不怕天黑_0819

责任链模式的定义

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

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

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

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

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

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

系统设计的时候,注意区分主次就好,即哪部分是核心流程,哪部分是辅助流程,辅助流程是否有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<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();
        }

        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就好了,伪代码为:

<bean id="filterChain" class="xxx.xxx.xxx.FilterChain">
    <property name="studyPrepareFilterList">
        <list>
            <ref bean="washFaceFilter" />
            <ref bean="washHairFilter" />
            <ref bean="haveBreakfastFilter" />
        </list>
    </property>
</bean>

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

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

/**
 * 责任链模式
  */
public class Filter_Test {
    public static void main(String[] a) {
        Request request = new Request();
        request.str = "大家好,<script> 这是敏感词";
        Response response = new Response();
        response.str="response";
        FilterChain filterChain = new FilterChain();
        filterChain.add(new HTMLFilter()).add(new SensitiveFilter());
        filterChain.doFilter(request, response);
        System.out.println(request.str);
        System.out.println(response.str);
    }
}

interface Filter {
    boolean doFilter(Request request, Response response, FilterChain filterChain);
}

class HTMLFilter implements  Filter {
    @Override
    public boolean doFilter(Request request, Response response, FilterChain chain) {
        request.str = request.str.replace("<","[").replace(">","]")+ " HTMLFilter()";
        chain.doFilter(request, response);
        response.str+="--HTMLFilter()";
        return true;
    }
}

class SensitiveFilter implements  Filter {
    @Override
    public boolean doFilter(Request request, Response response, FilterChain chain) {
        request.str = request.str.replace("敏感词","非敏感词")+ " sensitiveFilter()";
        chain.doFilter(request, response);
        response.str+="--sensitiveFilter()";
        return true;
    }
}

class Request {
    String str;
}

class Response {
    String str;
}

class FilterChain {
    List<Filter> filters = new ArrayList<>();
    int pos = 0;

    public FilterChain add(Filter filter) {
        filters.add(filter);
        return this;
    }

    public boolean doFilter(Request request, Response response) {
        if(pos == filters.size()) {
            return false;
        }
        Filter filter = filters.get(pos++);
        return filter.doFilter(request, response, this);
    }

}

参考链接:
参考链接

上一篇 下一篇

猜你喜欢

热点阅读