详解Java实现设计模式之责任链模式

yizhihongxing

详解Java实现设计模式之责任链模式

一、概述

责任链模式(Chain of Responsibility Pattern)是一种对象行为型设计模式,其作用是减少请求发送者与接收者之间的耦合,通过使多个对象都有机会处理请求来解决请求的发送者和接收者之间的耦合关系。通常情况下,每个接收者都包含对另一个接收者的引用。如果一个对象不能处理该请求,它会把相同的请求传递给下一个接收者,以此类推,形成责任链。

二、优缺点

优点:

  1. 多个对象可以处理同一个请求,具有很好的灵活性和扩展性。
  2. 请求的发送者和接收者解耦,两者不存在直接关联。
  3. 更好的封装性和可维护性,责任链只需要关心自己的处理对象,不关心其他对象。

缺点:

  1. 责任链长度过长,可能会影响责任链传递的效率。
  2. 如果责任链节点没有被正确配置,可能会造成循环调用或者死循环,导致系统崩溃。

三、示例说明

示例一

场景描述:一个公司有3个部门,人事部、财务部和技术部,每个部门有一个负责人,员工请假需要先向其所在部门的负责人提交请假申请,如果负责人无法批准,则需要上级领导处理。

// 申请表
class LeaveRequest {
    private String name; // 姓名
    private int days; // 请假天数

    public LeaveRequest(String name, int days) {
        this.name = name;
        this.days = days;
    }

    public String getName() {
        return name;
    }

    public int getDays() {
        return days;
    }
}

// 抽象处理者
interface Handler {
    // 处理请求
    boolean handleRequest(LeaveRequest leaveRequest);

    // 设置下一个处理者
    void setNextHandler(Handler handler);
}

// 具体处理者-人事部负责人
class PersonnelHandler implements Handler {
    private Handler nextHandler;

    @Override
    public boolean handleRequest(LeaveRequest leaveRequest) {
        if (leaveRequest.getDays() <= 3) {
            System.out.println("人事部负责人批准" + leaveRequest.getName() + "的请假申请,天数为" + leaveRequest.getDays() + "天");
            return true;
        } else {
            if (nextHandler != null) {
                return nextHandler.handleRequest(leaveRequest);
            } else {
                return false;
            }
        }
    }

    @Override
    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }
}

// 具体处理者-财务部负责人
class FinanceHandler implements Handler {
    private Handler nextHandler;

    @Override
    public boolean handleRequest(LeaveRequest leaveRequest) {
        if (leaveRequest.getDays() <= 5) {
            System.out.println("财务部负责人批准" + leaveRequest.getName() + "的请假申请,天数为" + leaveRequest.getDays() + "天");
            return true;
        } else {
            if (nextHandler != null) {
                return nextHandler.handleRequest(leaveRequest);
            } else {
                return false;
            }
        }
    }

    @Override
    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }
}

// 具体处理者-技术部负责人
class TechnicalHandler implements Handler {
    private Handler nextHandler;

    @Override
    public boolean handleRequest(LeaveRequest leaveRequest) {
        if (leaveRequest.getDays() <= 7) {
            System.out.println("技术部负责人批准" + leaveRequest.getName() + "的请假申请,天数为" + leaveRequest.getDays() + "天");
            return true;
        } else {
            if (nextHandler != null) {
                return nextHandler.handleRequest(leaveRequest);
            } else {
                return false;
            }
        }
    }

    @Override
    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }
}

// 责任链客户端
public class Client {

    public static void main(String[] args) {
        Handler personnelHandler = new PersonnelHandler();
        Handler financeHandler = new FinanceHandler();
        Handler technicalHandler = new TechnicalHandler();

        personnelHandler.setNextHandler(financeHandler);
        financeHandler.setNextHandler(technicalHandler);

        LeaveRequest request1 = new LeaveRequest("小明", 2);
        LeaveRequest request2 = new LeaveRequest("小红", 4);
        LeaveRequest request3 = new LeaveRequest("小刚", 6);
        LeaveRequest request4 = new LeaveRequest("小何", 10);

        personnelHandler.handleRequest(request1);
        personnelHandler.handleRequest(request2);
        personnelHandler.handleRequest(request3);
        personnelHandler.handleRequest(request4);
    }
}

运行结果:

人事部负责人批准小明的请假申请,天数为2天
财务部负责人批准小红的请假申请,天数为4天
技术部负责人批准小刚的请假申请,天数为6天

示例二

场景描述:一个人喜欢看动作电影和喜剧电影,他有两个电影分类的账号,为了避免每次登录都要进行选择分类,他希望选择一个账号后能自动显示和该账号对应的电影分类列表。

// 抽象处理者
public abstract class Handler {
    private Handler nextHandler;
    protected String account;

    public Handler(String account) {
        this.account = account;
    }

    // 处理请求
    public void handleRequest(String account) {
        if (account.equals(this.account)) {
            this.display();
        } else {
            if (nextHandler != null) {
                nextHandler.handleRequest(account);
            } else {
                System.out.println("没有找到该账号的电影分类列表");
            }
        }
    }

    public void setNextHandler(Handler handler) {
        this.nextHandler = handler;
    }

    public abstract void display();
}

// 具体处理者-动作电影分类列表
public class ActionHandler extends Handler {
    public ActionHandler(String account) {
        super(account);
    }

    @Override
    public void display() {
        System.out.println(this.account + ": 动作电影分类列表");
    }
}

// 具体处理者-喜剧电影分类列表
public class ComedyHandler extends Handler {
    public ComedyHandler(String account) {
        super(account);
    }

    @Override
    public void display() {
        System.out.println(this.account + ": 喜剧电影分类列表");
    }
}

// 责任链客户端
public class Client {

    public static void main(String[] args) {
        Handler actionHandler1 = new ActionHandler("账户1");
        Handler comedyHandler1 = new ComedyHandler("账户1");
        Handler actionHandler2 = new ActionHandler("账户2");
        Handler comedyHandler2 = new ComedyHandler("账户2");

        actionHandler1.setNextHandler(comedyHandler1);
        comedyHandler1.setNextHandler(actionHandler2);
        actionHandler2.setNextHandler(comedyHandler2);

        actionHandler1.handleRequest("账户1");
        actionHandler1.handleRequest("账户2");
        actionHandler1.handleRequest("账户3");
    }
}

运行结果:

账户1: 动作电影分类列表
账户2: 喜剧电影分类列表
没有找到该账号的电影分类列表

四、总结

责任链模式可以有效地解决请求发送者和接收者之间的耦合关系,使得多个对象都有机会处理同一个请求。在实际应用中,我们可以根据具体需求将责任链设置为不同的长度和顺序,以及不同的处理方式。同时,要注意控制责任链的长度和避免循环调用和死循环的出现,从而保证程序的正常运行和可维护性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解Java实现设计模式之责任链模式 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • Vue el-table实现右键菜单功能

    Vue el-table实现右键菜单功能的攻略如下: 一、实现思路 Vue el-table实现右键菜单功能的主要思路是:通过vue指令或自定义指令,实现鼠标右键点击el-table行时,弹出菜单框,并显示相应菜单项。 二、实现步骤 引入Element UI,安装并导入el-table组件; 安装并导入vue-contextmenu组件,该组件为右键菜单插件…

    other 2023年6月27日
    00
  • iphone6呼叫失败不能打电话的五种解决方案

    iPhone6呼叫失败不能打电话的五种解决方案 如果你的iPhone6不能打电话,它将变得没有用处,也会毁掉你的一天。以下是五种解决呼叫失败的方案: 1. 重新启动iPhone 这是最简单也是最常见的解决方法。按住电源键,滑动 “关机” 按钮,然后再按下电源键重新启动你的iPhone。如果你的iPhone不响应,请尝试按住电源键和”Home”按钮来强制重启。…

    other 2023年6月26日
    00
  • JavaScript基础心法 数据类型

    JavaScript基础心法:数据类型 JavaScript是一种动态弱类型语言,变量的类型会根据赋值自动推导,因此了解JavaScript中的数据类型是编写高质量代码的基础。本文将详细介绍JavaScript中的数据类型,以及常用操作。 数据类型 JavaScript中的数据类型可分为两大类:原始类型和对象类型。 原始类型 原始类型包括字符串、数字、布尔值…

    other 2023年6月27日
    00
  • 解决Golang小数float64在实际工程中加减乘除的精度问题

    一、背景 在实际工程开发中,我们经常会遇到计算金融、税费等场景,这时我们需要使用小数进行加减乘除等运算。而Golang使用float64存储小数,但是在精度计算中由于二进制存储特性,可能会出现不精确的情况。以下是如何解决Golang小数float64在实际工程中加减乘除的精度问题的完整攻略。 二、解决方案 1.使用Decimal等高精度计算库 Golang中…

    other 2023年6月27日
    00
  • Java编程访问权限的控制代码详解

    Java编程访问权限的控制代码详解 在Java编程中,访问权限控制是一种重要的机制,用于限制类、方法和变量的访问范围。本攻略将详细讲解Java中的访问权限控制代码。 1. 访问权限修饰符 Java提供了四种访问权限修饰符,分别是: public:公共访问权限,可以被任何类访问。 protected:受保护访问权限,可以被同一包内的类和子类访问。 defaul…

    other 2023年10月12日
    00
  • 易语言解析音悦台MV提供超清下载地址的代码

    易语言解析音悦台MV提供超清下载地址的代码攻略 简介 本攻略将详细讲解如何使用易语言编写代码来解析音悦台MV并提供超清下载地址。音悦台是一个流行的音乐MV分享平台,但官方并未提供超清下载选项。通过解析音悦台的页面,我们可以获取到超清下载地址,并将其提供给用户。 步骤 步骤一:获取音悦台MV页面源码 首先,我们需要获取音悦台MV的页面源码。可以使用易语言提供的…

    other 2023年8月4日
    00
  • PyGame实现初始化导入所有模块方法详解

    PyGame是一款专门用于开发2D游戏的Python库,使用PyGame可以轻松地创建游戏窗口、处理图像、音频等多种功能。在使用PyGame开发游戏时,我们需要对PyGame进行初始化和导入所有需要的模块。下面是PyGame实现初始化导入所有模块方法的详细攻略。 初始化 PyGame中的初始化是必要的,它为开发者提供了一些必要的游戏环境设置。PyGame提供…

    other 2023年6月20日
    00
  • npm全局环境变量配置详解

    npm全局环境变量配置详解 在使用npm包的时候,有时需要在全局安装某个包,并在命令行中使用该包的命令。这时候就需要配置npm的全局环境变量。下面是详细的配置步骤: 第一步:设置npm全局安装路径 通过以下命令设置npm全局安装包的路径: npm config set prefix "/usr/local" 其中,”/usr/local”…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部