• 详解Java设计模式之职责链模式


    原文:详解Java设计模式之职责链模式_java_脚本之家

    责任链模式是一种行为设计模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,文中通过代码示例给大家介绍的非常详细,需要的朋友可以参考下

    Java技术迷

    目录

    职责链模式

    1、职责链模式介绍

    责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这个对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

    在责任链模式中,请求通过一条链传递,每个对象都有机会处理请求。当一个对象无法处理请求时,它会将请求传递给链中的下一个对象,直到找到能够处理请求的对象为止。这种方式可以动态地组织和管理对象,使得请求发送者和接收者之间解耦,提高系统的灵活性和可扩展性。

    1.1 职责链模式基本实现

    职责链模式结构图:

    责任链模式包含以下几个角色:

    • 抽象处理者(Handler):定义了一个处理请求的接口,通常包含一个指向下一个处理者的引用,用于构建责任链。
    • 具体处理者(ConcreteHandler):实现抽象处理者接口,具体处理请求的逻辑。如果可以处理请求,则处理请求;否则,将请求传递给下一个处理者。

    Handler类,定义一个处理请示的接口:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:04

     * 处理请求的接口

     */

    public abstract class Handler {

        protected Handler successor;

        /**

         * 设置继承者

         * @param successor

         */

        public void setSuccessor(Handler successor) {

            this.successor = successor;

        }

        public abstract void handleRequest(int request);

    }

    ConcreteHandler类,具体处理者类,处理它所负责的请求,可访问它的 后继者,如果可处理该请求,就处理之,否则就将该请求转发给它的后继 者。

    ConcreteHandler1,当请求数为0~10则有权处理,否则转到下一位:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:06

     */

    public class ConcreteHandler1 extends Handler {

        @Override

        public void handleRequest(int request) {

            if (request >= 0 && request < 10) {

                // 当前处理者权限 0 ~ 9

                System.out.println(this.getClass().getSimpleName() + "处理了请求" + request);

            } else if (successor != null) {

                // 转移给下一个处理者

                successor.handleRequest(request);

            }

        }

    }

    ConcreteHandler2,当请求数为10~20则有权处理,否则转到下一位。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:06

     */

    public class ConcreteHandler2 extends Handler {

        @Override

        public void handleRequest(int request) {

            if (request >= 10 && request < 20) {

                // 当前处理者权限 10 ~ 19

                System.out.println(this.getClass().getSimpleName() + "处理了请求" + request);

            } else if (successor != null) {

                // 转移给下一个处理者

                successor.handleRequest(request);

            }

        }

    }

    ConcreteHandler3,当请求数为20~99则有权处理,否则转到下一位

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:06

     */

    public class ConcreteHandler3 extends Handler {

        @Override

        public void handleRequest(int request) {

            if (request >= 20 && request < 100) {

                // 当前处理者权限 20 ~ 99

                System.out.println(this.getClass().getSimpleName() + "处理了请求" + request);

            } else if (successor != null) {

                // 转移给下一个处理者

                successor.handleRequest(request);

            }

        }

    }

    客户端代码,向链上的具体处理者对象提交请求。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:09

     */

    public class ChainClient {

        public static void main(String[] args) {

            ConcreteHandler1 handler1 = new ConcreteHandler1();

            ConcreteHandler2 handler2 = new ConcreteHandler2();

            ConcreteHandler3 handler3 = new ConcreteHandler3();

            // 设置职责链上下关系

            handler1.setSuccessor(handler2);

            handler2.setSuccessor(handler3);

            // 请求

            int[] request = {15, 67, 8, 9, 46, 1, 5, 23, 41};

            // 循环给最小矗立着提交请求,不同的数额,得不同的权限处理者处理

            for (int i : request) {

                handler1.handleRequest(i);

            }

        }

    }

    2、具体例子说明

    在公司请假或者升职加薪,需要通过经理、总监、总经理的批准,不同身份有不同的权限。当然可以直接直接找总经理给你升职加薪😎

    2.1 不使用职责链模式 - 加薪 / 请假

    升值加薪:经理是没有权限的,要上报给总监,总监的回复也是没有权限管,只能再上报到总经理才有处理的权限

    请假:经理只能处理请假两天的申请,再多就不可以。必须要上报给上司才有权限去处理这个请求。

    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

    // 申请类

    public class Request {

        // 申请类别

        private String requestType;

        public String getRequestType(){

            return this.requestType;

        }

        public void setRequestType(String value){

            this.requestType = value;

        }

        //申请内容

        private String requestContent;

        public String getRequestContent(){

            return this.requestContent;

        }

        public void setRequestContent(String value){

            this.requestContent = value;

        }

        // 数量

        private int number;

        public int getNumber(){

            return this.number;

        }

        public void setNumber(int value){

            this.number = value;

        }

    }

    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

    //管理者

    public class Manager{

        protected String name;

        public Manager(String name){

            this.name = name;

        }

        public void getResult(String managerLevel,Request request){

            if (managerLevel == "经理"){

              if (request.getRequestType()=="请假" && request.getNumber()<=2)

                System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,被批准");

              else

                System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,我无权处理");

            }

            else if (managerLevel == "总监"){

              if (request.getRequestType()=="请假" && request.getNumber()<=5)

                System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,被批准");

              else

                System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,我无权处理");

            }

            else if (managerLevel == "总经理"){

              if (request.getRequestType()=="请假")

                System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"天,被批准");

              else if (request.getRequestType()=="加薪" && request.getNumber()<=5000)

                System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"元,被批准");

              else if (request.getRequestType()=="加薪" && request.getNumber()>5000)

                System.out.println(this.name+":"+request.getRequestContent()+" 数量:"+request.getNumber()+"元,再说吧");

            }

        }

    }

    客户端:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    public class Test {

        public static void main(String[] args) {

            Manager manager = new Manager("金利");

            Manager director = new Manager("宗剑");

            Manager generalManager = new Manager("钟精励");

            Request request = new Request();

            request.setRequestType("加薪");

            request.setRequestContent("Shier请求加薪");

            request.setNumber(10000);

            // 不同身份的人有不同的权限,进行处理结果

            manager.getResult("经理", request);

            director.getResult("总监", request);

            generalManager.getResult("总经理", request);

            Request request2 = new Request();

            request2.setRequestType("请假");

            request2.setRequestContent("Shier请假");

            request2.setNumber(3); // 权限级别

            manager.getResult("经理", request2);

            director.getResult("总监", request2);

            generalManager.getResult("总经理", request2);

        }

    }

    通过上面的程序,会发现一个问题管理者类,里面的方法比较长,太多的分支判断。类的责任太多,就违背了单一职责原则,同时增加新的项目时,要去修改这个方法,就违背了开发 - 封闭原则。下面就要用到职责链模式要简化这样开发业务场景 。

    2.2 职责链模式 - 加薪 / 请假

    将上面的程序进行重构,得到的代码结构图如下:

    Request请求类:

    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

    /**

     * @author Shier

     * 申请类

     */

    public class Request {

        // 申请类别

        private String requestType;

        public String getRequestType() {

            return this.requestType;

        }

        public void setRequestType(String value) {

            this.requestType = value;

        }

        //申请内容

        private String requestContent;

        public String getRequestContent() {

            return this.requestContent;

        }

        public void setRequestContent(String value) {

            this.requestContent = value;

        }

        // 数量

        private int number;

        public int getNumber() {

            return this.number;

        }

        public void setNumber(int value) {

            this.number = value;

        }

    }

    抽象管理者:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:33

     * 抽象管理这类

     */

    public abstract class Manager {

        protected String name;

        public Manager(String name) {

            this.name = name;

        }

        /**

         * 设置管理者上级

         */

        protected Manager superior;

        public void setSuperior(Manager superior) {

            this.superior = superior;

        }

        /**

         * 请求申请

         *

         * @param request

         */

        public abstract void requestApplications(Request request);

    }

    经理类就可以去继承这个'管理者'类,只需重写 '申请请求' 的方法

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:34

     * 普通经理类

     */

    public class CommonManager extends Manager {

        public CommonManager(String name) {

            super(name);

        }

        @Override

        public void requestApplications(Request request) {

            if (request.getRequestType() == "请假" && request.getNumber() <= 2) {

                System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "天,被批准");

            } else if (this.superior != null) {

                this.superior.requestApplications(request);

            }

        }

    }

    总监同样继承抽象管理类

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:36

     * 总监

     */

    public class Director extends Manager {

        public Director(String name) {

            super(name);

        }

        @Override

        public void requestApplications(Request request) {

            if (request.getRequestType() == "请假" && request.getNumber() <= 5) {

                System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "天,被批准");

            } else if (this.superior != null) {

                this.superior.requestApplications(request);

            }

        }

    }

    总经理同样继承管理者类,总经理的权限就是全部都需要处理。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    /**

     * @author Shier

     * CreateTime 2023/5/20 16:36

     * 总经理

     */

    public class GeneralManager extends Manager {

        public GeneralManager(String name) {

            super(name);

        }

        @Override

        public void requestApplications(Request request) {

            if (request.getRequestType() == "请假") {

                System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "天,被批准");

            } else if (request.getRequestType() == "加薪" && request.getNumber() <= 5000) {

                System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "元,被批准");

            } else if (request.getRequestType() == "加薪" && request.getNumber() > 5000) {

                System.out.println(this.name + ":" + request.getRequestContent() + " 数量:" + request.getNumber() + "元,再说吧");

            }

        }

    }

    测试类:

    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

    /**

     * @author Shier

     */

    public class ChainClient {

        public static void main(String[] args) {

            CommonManager manager = new CommonManager("大明经理");

            Director director = new Director("大大明总监");

            GeneralManager generalManager = new GeneralManager("大大大明总经理");

            // 设置管理者之间上下级关系 经理 => 总监 => 总经理

            manager.setSuperior(director);

            director.setSuperior(generalManager);

            // 加薪 5000

            Request request = new Request();

            request.setRequestType("加薪");

            request.setRequestContent("Shier请求加薪");

            request.setNumber(5000);

            // 从自己最近的上司开始请求也就是经理

            manager.requestApplications(request);

            // 加薪10000

            Request request1 = new Request();

            request1.setRequestType("加薪");

            request1.setRequestContent("Shier请求加薪");

            request1.setNumber(10000);

            manager.requestApplications(request1);

            // 请假一天

            Request request2 = new Request();

            request2.setRequestType("请假");

            request2.setRequestContent("Shier请假");

            request2.setNumber(1);

            manager.requestApplications(request2);

            // 请假四天

            Request request3 = new Request();

            request3.setRequestType("请假");

            request3.setRequestContent("Shier请假");

            request3.setNumber(4);

            manager.requestApplications(request3);

        }

    }

    最后得到的结果:

    由于我们把原来的一个 '管理者' 类改成了一个抽象类和三个具体类, 此时类之间的灵活性就大大增加了,如果我们需要扩展新的管理者类别,只需要增加子类就可以。比如这个例子增加一个 '集团总裁' 类,完全是没有问题的,只需要修改 '总经理类' 即可,并不影响其他类代码。

    这样使用职责链模式可以更加清晰这些代码之间的关系,不像最上面的一个类里面多个判断语句,看起来都很难维护。好了,再总结一下职责链模式

    3、职责链模式总结

    职责链模式的好处

    • 当客户提交一个请求时,请求是沿链传递直至有一个 ConcreteHandler 对象负责处理它。
    • 降低耦合:接收者和发送者都没有对方的明确信息,且链中的对 象自己也并不知道链的结构。结果是职责链可简化对象的相互连接,它们仅 需保持一个指向其后继者的引用,而不需保持它所有的候选接受者的引用。降低了代码之间耦合度。
    • 灵活性:随时地增加或修改处理一个请求的结构。增强了给对象指派职责的灵活性。

    优点:

    • 将请求发送者和接收者解耦,可以避免请求发送者与接收者之间的直接耦合,增强了代码的可维护性。
    • 可以动态地新增或修改请求处理顺序,提高了程序的灵活性和可扩展性。
    • 可以进行请求的拦截、分流等操作,方便进行统计和日志记录等处理。
    • 可以根据需要对请求的处理进行单独的测试,便于代码测试和调试。
    • 解耦发送者和接收者:职责链模式可以将发送者和接收者解耦,发送者不需要知道请求的具体处理者是谁,而处理者也不需要知道请求的发送者是谁,从而提高系统的灵活性。
    • 动态组合和扩展性:职责链模式允许动态地向链中添加或删除处理者,以适应不同的业务需求,增强了系统的可扩展性。
    • 可配置性:通过调整链中处理者的顺序,可以灵活地配置处理流程,满足不同的处理优先级或条件。

    缺点:

    • 请求的保证:没有明确的处理者处理请求的保证。请求可能到达链的末尾而没有被处理,这需要在设计时进行合理的考虑。
    • 性能考虑:由于链中的请求需要依次传递给每个处理者,因此在处理大量请求时可能会影响性能。
    • 可能导致系统变得复杂:当链过长或者处理者过多时,职责链模式可能会导致系统变得复杂,难以理解和维护。

    使用场景:

    • 处理复杂的请求处理流程,例如购物车结算、审批流程等复杂业务中。
    • 需要动态指定请求的处理顺序或者动态添加新的请求处理者时。
    • 处理日志记录、缓存等拦截器的场景。例如在Spring中,就应用了责任链模式来实现Interceptor拦截器。
    • 多个对象可以处理同一请求,但具体的处理者在运行时可变或不确定的情况下,可以使用职责链模式。
    • 需要动态组合处理流程或动态调整处理顺序的情况下,职责链模式可以提供灵活性和可配置性。
    • 需要在不明确请求的发送者和接收者之间建立松耦合关系的情况下,职责链模式可以解耦对象之间的关系。

    以上就是详解Java设计模式之职责链模式的详细内容,更多关于Java 职责链模式的资料请关注脚本之家其它相关文章!

    您可能感兴趣的文章:

  • 相关阅读:
    视频翻译字幕的软件哪个好?看完你就知道了
    浏览器上写代码,4核8G微软服务器免费用,Codespaces真香
    如何读写txt文件 C++读和写txt文件操作
    基于卷积神经网络ResUnet 多模态融合实验、BraTS 3d数据集(nii.gz)4模态融合分割
    静态Static 动态代码块 静态代码块 类加载
    CSS 3之美化表格样式
    DeepAR多重多元多步时间序列预测
    git上传项目的基本步骤与一些问题
    【11.1】【VP】Codeforces Round #730 (Div. 2)
    【DL with Pytorch】第 5 章 :风格迁移
  • 原文地址:https://blog.csdn.net/javastart/article/details/134487408