• 详解设计模式:责任链模式


    责任链模式(Chain of Responsibility Pattern)也被称为职责链模式,是在 GoF 23 种设计模式中定义了的行为型模式。

    责任链模式 是将链中的每一个节点看作是一个对象,每个节点处理的请求不同,且内部自动维护一个下一节点对象。当一个请求从链式的首段发出时,会沿着链的路径依此传递给每一个节点对象,直至有对象处理这个请求为止。

    责任链模式 将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

    本篇文章内容包括:关于责任链模式、责任链模式 Demo(伪代码)、责任链模式 Demo(模拟 FilterChain



    一、关于责任链模式

    1、关于链式模式

    首先它可以对同一模块中有先后执行顺序要求的类或对象进行成链,以达到高聚合的目的。同时对于单一执行状态下的执行步骤,可以通过非状态模式的成链方式进行组装,便可以实现改变执行顺序的目的,让代码维护性变高。

    2、关于责任链模式

    责任链模式(Chain of Responsibility Pattern)也被称为职责链模式,是在 GoF 23 种设计模式中定义了的行为型模式。

    责任链模式 是将链中的每一个节点看作是一个对象,每个节点处理的请求不同,且内部自动维护一个下一节点对象。当一个请求从链式的首段发出时,会沿着链的路径依此传递给每一个节点对象,直至有对象处理这个请求为止。

    责任链模式 将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求。将这些接收对象串成一条链,并沿着这条链传递这个请求,直到链上的某个接收对象能够处理它为止。

    3、关于责任链模式的构成

    责任链模式主要包含以下 2 种角色:

    • 抽象处理者(Handler)角色:定义出一个处理请求的接口。如果需要,接口可以定义 出一个方法以设定和返回对下家的引用。这个角色通常由一个 Java 抽象类或者 Java 接口实现。Handler 类的聚合关系给出了具体子类对下家的引用,抽象方法 handleRequest() 规范了子类处理请求的操作。
    • 具体处理者(ConcreteHandler)角色:具体处理者接到请求后,可以选择将请求处理掉,或者将请求传给下家。由于具体处理者持有对下家的引用,因此,如果需要,具体处理者可以访问下家。
    4、关于责任链模式的XML

    image-20221203204424308

    5、关于责任链模式的处理流程

    image-20221203204403335

    6、关于责任链模式的应用场景
    • 职责链模式最常用来开发框架的过滤器和拦截器
    • 多个对象可以处理一个请求,但具体由哪个对象处理该请求在运行时自动确定。
    • 可动态指定一组对象处理请求,或添加新的处理者。
    • 需要在不明确指定请求处理者的情况下,向多个处理者中的一个提交请求。
    7、关于责任链模式的优缺点

    # 责任链模式的优点

    • 降低了对象之间的耦合度。该模式使得一个对象无须知道到底是哪一个对象处理其请求以及链的结构,发送者和接收者也无须拥有对方的明确信息。
    • 增强了系统的可扩展性。可以根据需要增加新的请求处理类,满足开闭原则。
    • 增强了给对象指派职责的灵活性。当工作流程发生变化,可以动态地改变链内的成员或者调动它们的次序,也可动态地新增或者删除责任。
    • 责任链简化了对象之间的连接。每个对象只需保持一个指向其后继者的引用,不需保持其他所有处理者的引用,这避免了使用众多的 if 或者 if···else 语句。
    • 责任分担。每个类只需要处理自己该处理的工作,不该处理的传递给下一个对象完成,明确各类的责任范围,符合类的单一职责原则。

    # 责任链模式的缺点

    • 不能保证每个请求一定被处理。由于一个请求没有明确的接收者,所以不能保证它一定会被处理,该请求可能一直传到链的末端都得不到处理。
    • 对比较长的职责链,请求的处理可能涉及多个处理对象,系统性能将受到一定影响。
    • 职责链建立的合理

    二、责任链模式 Demo(伪代码)

    1、伪代码 Demo 实现

    # Handler

    public abstract class Handler {
    
        private Handler next;
    
        /**
         * 用来设置下一个处理者
         * @param next Handler
         */
        public void setNext(Handler next) {
            this.next=next;
        }
        public Handler getNext() {
            return next;
        }
    
        /**
         * 处理请求的方法
         * @param request String
         */
        public abstract void handleRequest(String request);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    # ConcreteHandler

    public class ConcreteHandler1 extends Handler {
    
        @Override
        public void handleRequest(String request) {
            if("one".equals(request))  {
                System.out.println("具体处理者1负责处理该请求!");
            }
            else {
                if(getNext()!=null)  {
                    getNext().handleRequest(request);
                }
                else {
                    System.out.println("没有人处理该请求!");
                }
            }
        }
    }
    public class ConcreteHandler2 extends Handler {
    
        @Override
        public void handleRequest(String request) {
            if("two".equals(request))  {
                System.out.println("具体处理者2负责处理该请求!");
            }
            else {
                if(getNext()!=null) {
                    getNext().handleRequest(request);
                }
                else {
                    System.out.println("没有人处理该请求!");
                }
            }
        }
    }
    
    • 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
    2、Demo 测试
    public class Client {
        public static void main(String[] args) {
            //组装责任链
            Handler handler1 = new ConcreteHandler1();
            Handler handler2 = new ConcreteHandler2();
            handler1.setNext(handler2);
            //提交请求
            handler1.handleRequest("two");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    三、责任链模式 Demo(模拟 FilterChain)

    1、Demo 设计

    在 JavaWeb 应用开发中,FilterChain 是职责链(过滤器)模式的典型应用,以下是 Filter 的模拟实现分析

    2、Demo 实现

    # 模拟 web 请求 Request 以及 web 响应 Response

    public interface Request{}
    
    public interface Response{}
    
    • 1
    • 2
    • 3

    # Filter 过滤器

    public interface Filter {
     		public void doFilter(Request req,Response res,FilterChain c);
    }
    
    • 1
    • 2
    • 3

    # FirstFilter 具体过滤器

    public class FirstFilter implements Filter {
        @Override
        public void doFilter(Request request, Response response, FilterChain chain) {
    
            System.out.println("过滤器1 前置处理");
    
            // 先执行所有request再倒序执行所有response
            chain.doFilter(request, response);
    
            System.out.println("过滤器1 后置处理");
        }
    }
    
    public class SecondFilter  implements Filter {
        @Override
        public void doFilter(Request request, Response response, FilterChain chain) {
    
            System.out.println("过滤器2 前置处理");
    
            // 先执行所有request再倒序执行所有response
            chain.doFilter(request, response);
    
            System.out.println("过滤器2 后置处理");
        }
    }
    
    
    • 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

    # FilterChain 过滤器链

    public class FilterChain {
    
        private List<Filter> filters = new ArrayList<Filter>();
    
        private int index = 0;
    
        // 链式调用
        public FilterChain addFilter(Filter filter) {
            this.filters.add(filter);
            return this;
        }
    
        public void doFilter(Request request, Response response) {
            if (index == filters.size()) {
                return;
            }
            Filter filter = filters.get(index);
            index++;
            filter.doFilter(request, response, this);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    3、Demo 测试
    public class Client {
        public static void main(String[] args) {
            Request  req = null;
            Response res = null ;
    
            FilterChain filterChain = new FilterChain();
            filterChain.addFilter(new FirstFilter()).addFilter(new SecondFilter());
            filterChain.doFilter(req,res);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    Python中Collections模块namedtuple用法
    获取购物车的商品列表
    厉害了!有了它,发顶会顶刊拿赛事大奖轻松多了!
    dreamweaver作业静态HTML网页设计——家乡海南旅游网站
    找工作八股文----《计算机网络》
    互斥量保护资源
    阿里P8架构大神分享纯手写“kafka文档”看完直呼太牛!
    【Java基础篇】逻辑控制
    《打造高可用PostgreSQL:策略与工具》
    【一】情感对话 Towards Emotional Support Dialog Systems 论文阅读
  • 原文地址:https://blog.csdn.net/weixin_45187434/article/details/128171017