美文网首页
设计模式之责任链模式

设计模式之责任链模式

作者: 不怕天黑_0819 | 来源:发表于2020-06-26 16:15 被阅读0次

    责任链模式的定义

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

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

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

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

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

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

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

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

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

    参考链接:
    参考链接

    相关文章

      网友评论

          本文标题:设计模式之责任链模式

          本文链接:https://www.haomeiwen.com/subject/djvyfktx.html