• Java核心篇,二十三种设计模式(十三),行为型——责任链模式


    一、概念

    将多个对象通过引用连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象决定处理此请求。对于客户来说并不知道请求在哪一个环节被处理了。从而实现了请求和处理之间的解耦合

    二、特点

    • 有多个请求处理者
    • 所有请求的处理者通过前一对象记住其下一个对象的引用而连成一条链
    • 请求沿着这条链传递,直到有对象处理它为止

    责任链模式在处理请求的过程中,可能出现以下的情况:

    如果请求能被当前handler处理,则先执行特定的处理根据处理流程,当前handler处理完成后,可能有以下两种情况:

    • 可能不再向next handler传递,结束整个处理流程,如请假审批;上一级同意后,事件处理完成
    • 可能继续向next handler传递,直到到达责任链末尾,如奖学金评选;上一级同意后,才能传递给下一级

    如果请求不能被当前handler处理,则需要向next handler传递

    可能不存在对应的handler,导致请求无法被处理

    三、适用场景

    • 有多个的对象可以处理一个请求,哪个对象处理该请求运行时刻自动确定
    • 在不明确指定接收者的情况下,向多个对象中的一个提交一个请求
    • 可处理一个请求的对象集合应被动态指定

    四、成员角色

    • 抽象处理者(Handler):一般为抽象类,定义一个处理请求的抽象方法,它规范了每一个具体处理者的信息;包含一个指向后继处理者的 next 引用,以构造责任链
    • 具体处理者(Concrete Handler):实现抽象处理者的处理方法,根据实际情况决定是否处理请求,是否传递请求给后继处理者
    • 客户类(Client):创建责任链,向责任链头部的具体处理者对象提交请求,不关心请求的处理细节和传递过程

    五、优缺点

    优点

    • 降低了对象之间的耦合度,发送者无需知道最终由哪一个handler处理其请求,也无需知道请求的传递过程
    • 增强了系统的可扩展性,如果新增handler无需修改请求者的代码逻辑,满足开闭原则
    • 增强了给对象指派职责的灵活性,随着工作流程的变化,可以动态地改变链内的handler、可以动态地调整handler的次序,还可以动态地增加或删除handler
    • 简化了对象之间的连接,每个对象只需保持一个指向其后继者的next引用,不需保持其他所有处理者的引用,避免了使用众多的 if···else 语句
    • 责任分担方面,每个handler只需要处理自己分内的工作,分外的工作可以传递给下一个handler去完成,这样的话,每个handler的分工明确,符合类的单一职责原则

    缺点

    • 不能保证每个请求一定被处理:传入责任链的请求,可能直到链的末尾都没有对应的handler可以处理它
    • 对比较长的责任链,请求的处理可能涉及多个handler,系统性能将受到一定影响。
    • 责任链建立的合理性由客户端保证,增加了客户端的复杂性
    • 可能会由于责任链的错误设置而导致系统出错,如循环调用

    六、案例分析

    小刘作为公司一名普通员工,现在有事情需要请假,公司领导层分为:组长、部门经理、老板。其中组长可以审批3天以内的假,部门经理可以审批5天以内的假,超过5天的假必须找老板审批,超过七天的假会被拒回。公司中能跟普通员工直接工作交接的只有组长,不存在跨级工作交接的情况

    七、代码实现

    7.1 普通版本

    Handler

    1. package com.behaviour.chains.common.Handler;
    2. import com.behaviour.chains.common.HolidayEvent;
    3. /**
    4. * 抽象处理者(Handler)
    5. * 供具体处理者继承,规范了每一个具体处理者的基本功能
    6. */
    7. public abstract class Handler {
    8. private Handler next;
    9. public void setNext(Handler next) {
    10. this.next = next;
    11. }
    12. public Handler getNext() {
    13. return next;
    14. }
    15. public abstract void handleRequest(HolidayEvent event);
    16. }

    GroupLeader

    1. package com.behaviour.chains.common.ConcreteHandler;
    2. import com.behaviour.chains.common.Handler.Handler;
    3. import com.behaviour.chains.common.HolidayEvent;
    4. public class GroupLeader extends Handler {
    5. @Override
    6. public void handleRequest(HolidayEvent event) {
    7. if (event.getDays() <= 3){
    8. System.out.println(event.getName() + "同志,组长已经审批通过您长达" + event.getDays() + "天的请假申请");
    9. }else{
    10. getNext().handleRequest(event);
    11. }
    12. }
    13. }

    ManageLeader

    1. package com.behaviour.chains.common.ConcreteHandler;
    2. import com.behaviour.chains.common.Handler.Handler;
    3. import com.behaviour.chains.common.HolidayEvent;
    4. public class ManageLeader extends Handler {
    5. @Override
    6. public void handleRequest(HolidayEvent event) {
    7. if (event.getDays() <= 5){
    8. System.out.println(event.getName() + "同志,项目经理已经审批通过您长达" + event.getDays() + "天的请假申请");
    9. }else{
    10. getNext().handleRequest(event);
    11. }
    12. }
    13. }

    BossLeader

    1. package com.behaviour.chains.common.ConcreteHandler;
    2. import com.behaviour.chains.common.Handler.Handler;
    3. import com.behaviour.chains.common.HolidayEvent;
    4. public class BossLeader extends Handler {
    5. @Override
    6. public void handleRequest(HolidayEvent event) {
    7. if (event.getDays() <= 7){
    8. System.out.println(event.getName() + "同志,老板已经审批通过您长达" + event.getDays() + "天的请假申请");
    9. }else{
    10. System.out.println("请假时间过长,已被驳回");
    11. }
    12. }
    13. }

    HolidayOA

    1. package com.behaviour.chains.common.Client;
    2. import com.behaviour.chains.common.ConcreteHandler.BossLeader;
    3. import com.behaviour.chains.common.ConcreteHandler.GroupLeader;
    4. import com.behaviour.chains.common.ConcreteHandler.ManageLeader;
    5. import com.behaviour.chains.common.HolidayEvent;
    6. /**
    7. * 客户类(Client):创建责任链
    8. * 公司OA请假系统
    9. */
    10. public class HolidayOA {
    11. private GroupLeader groupLeader;
    12. private ManageLeader manageLeader;
    13. private BossLeader bossLeader;
    14. // 构造责任链
    15. public HolidayOA(){
    16. this.groupLeader = new GroupLeader();
    17. this.manageLeader = new ManageLeader();
    18. this.bossLeader = new BossLeader();
    19. this.groupLeader.setNext(manageLeader);
    20. this.manageLeader.setNext(bossLeader);
    21. }
    22. // 请假事件入口
    23. public void doHoliday(HolidayEvent event){
    24. this.groupLeader.handleRequest(event);
    25. }
    26. }

    HolidayEvent

    1. package com.behaviour.chains.common;
    2. /**
    3. * Handler要处理的事件
    4. * 请假事件
    5. */
    6. public class HolidayEvent {
    7. private String name;
    8. private Integer days;
    9. public HolidayEvent(String name, Integer days) {
    10. this.name = name;
    11. this.days = days;
    12. }
    13. public String getName() {
    14. return name;
    15. }
    16. public void setName(String name) {
    17. this.name = name;
    18. }
    19. public Integer getDays() {
    20. return days;
    21. }
    22. public void setDays(Integer days) {
    23. this.days = days;
    24. }
    25. }

    Test

    1. package com.behaviour.chains.common;
    2. import com.behaviour.chains.common.Client.HolidayOA;
    3. public class Test {
    4. public static void main(String[] args) {
    5. new HolidayOA().doHoliday(new HolidayEvent("小明", 4));
    6. }
    7. }

    7.2 升级版本

    Handler

    1. package com.behaviour.chains.upgrade.Handler;
    2. import com.behaviour.chains.upgrade.HolidayEvent;
    3. /**
    4. * 抽象处理者(Handler)
    5. * 供具体处理者继承,规范了每一个具体处理者的基本功能
    6. */
    7. public abstract class Handler {
    8. public abstract void handleRequest(HolidayEvent event);
    9. }

    GroupLeader

    1. package com.behaviour.chains.upgrade.ConcreteHandler;
    2. import com.behaviour.chains.upgrade.Handler.Handler;
    3. import com.behaviour.chains.upgrade.HolidayEvent;
    4. /**
    5. * 具体处理者(Concrete Handler)
    6. * 组长
    7. */
    8. public class GroupLeader extends Handler {
    9. @Override
    10. public void handleRequest(HolidayEvent event) {
    11. if (event.getDays() <= 3){
    12. System.out.println(event.getName() + "同志,组长已经审批通过您长达" + event.getDays() + "天的请假申请");
    13. event.setSuccessful(true);
    14. }
    15. }
    16. }

    ManageLeader

    1. package com.behaviour.chains.upgrade.ConcreteHandler;
    2. import com.behaviour.chains.upgrade.Handler.Handler;
    3. import com.behaviour.chains.upgrade.HolidayEvent;
    4. /**
    5. * 具体处理者(Concrete Handler)
    6. * 项目经理
    7. */
    8. public class ManageLeader extends Handler {
    9. @Override
    10. public void handleRequest(HolidayEvent event) {
    11. if (event.getDays() <= 5){
    12. System.out.println(event.getName() + "同志,项目经理已经审批通过您长达" + event.getDays() + "天的请假申请");
    13. event.setSuccessful(true);
    14. }
    15. }
    16. }

    BossLeader

    1. package com.behaviour.chains.upgrade.ConcreteHandler;
    2. import com.behaviour.chains.upgrade.Handler.Handler;
    3. import com.behaviour.chains.upgrade.HolidayEvent;
    4. /**
    5. * 具体处理者(Concrete Handler)
    6. * 老板
    7. */
    8. public class BossLeader extends Handler {
    9. @Override
    10. public void handleRequest(HolidayEvent event) {
    11. if (event.getDays() <= 7){
    12. System.out.println(event.getName() + "同志,老板已经审批通过您长达" + event.getDays() + "天的请假申请");
    13. event.setSuccessful(true);
    14. }else {
    15. System.out.println(event.getName() + "同志,您的请假时间过长,已撤销申请");
    16. }
    17. }
    18. }

    HandleChains

    1. package com.behaviour.chains.upgrade.ConcreteHandler;
    2. import com.behaviour.chains.upgrade.Handler.Handler;
    3. import com.behaviour.chains.upgrade.HolidayEvent;
    4. import java.util.ArrayList;
    5. import java.util.List;
    6. /**
    7. * 客户类(Client):创建责任链
    8. * 公司OA请假系统
    9. */
    10. public class HandleChains {
    11. private List<Handler> handlers;
    12. // 构造责任链
    13. public HandleChains(){
    14. handlers = new ArrayList<>();
    15. }
    16. public HandleChains addHandler(Handler handler){
    17. this.handlers.add(handler);
    18. return this;
    19. }
    20. public void execHandler(HolidayEvent event){
    21. for (Handler handler : this.handlers) {
    22. if (!event.getSuccessful()){
    23. handler.handleRequest(event);
    24. }
    25. }
    26. }
    27. }

    HolidayOA

    1. package com.behaviour.chains.upgrade.Client;
    2. import com.behaviour.chains.upgrade.ConcreteHandler.BossLeader;
    3. import com.behaviour.chains.upgrade.ConcreteHandler.GroupLeader;
    4. import com.behaviour.chains.upgrade.ConcreteHandler.HandleChains;
    5. import com.behaviour.chains.upgrade.ConcreteHandler.ManageLeader;
    6. import com.behaviour.chains.upgrade.HolidayEvent;
    7. /**
    8. * 客户类(Client):创建责任链
    9. * 公司OA请假系统
    10. */
    11. public class HolidayOA {
    12. private HandleChains chains;
    13. public HolidayOA(){
    14. chains = new HandleChains()
    15. .addHandler(new GroupLeader())
    16. .addHandler(new ManageLeader())
    17. .addHandler(new BossLeader());
    18. }
    19. public void doHoliday(HolidayEvent event){
    20. this.chains.execHandler(event);
    21. }
    22. }

    HolidayEvent

    1. package com.behaviour.chains.upgrade;
    2. /**
    3. * Handler要处理的事件
    4. * 请假事件
    5. */
    6. public class HolidayEvent {
    7. private String name;
    8. private Integer days;
    9. private Boolean isSuccessful;
    10. public HolidayEvent(String name, Integer days) {
    11. this.name = name;
    12. this.days = days;
    13. this.isSuccessful = false;
    14. }
    15. public String getName() {
    16. return name;
    17. }
    18. public Integer getDays() {
    19. return days;
    20. }
    21. public Boolean getSuccessful() {
    22. return isSuccessful;
    23. }
    24. public void setSuccessful(Boolean successful) {
    25. isSuccessful = successful;
    26. }
    27. }

    Test

    1. package com.behaviour.chains.upgrade;
    2. import com.behaviour.chains.upgrade.Client.HolidayOA;
    3. public class Test {
    4. public static void main(String[] args) {
    5. new HolidayOA().doHoliday(new HolidayEvent("小刘", 6));
    6. }
    7. }

  • 相关阅读:
    IT项目中需要规避的9类风险,你知道都有哪些吗?
    ElasticSearch学习笔记(一)es初体验
    HBase的逻辑结构与物理结构
    最小生成树prim算法
    k8s-namespace-基本概念
    国外LEAD收款渠道介绍:Wise收款教程
    小米机型安全删除内置软件列表 miui12 miui13 可删除内置
    CNN RNN DNN transformer 区别以及音频信号处理适合方式
    docker镜像与容器基本的基本操作
    循环跨3天活动的一次思考
  • 原文地址:https://blog.csdn.net/ITlanyue/article/details/125402618