责任链设计模式知多少

news2024/12/23 11:44:18

目录

目标

概述

实现

单向设计模式

双向设计模式


目标

熟悉责任链设计模式,了解责任链设计模式的使用场景、具体实现,单链责任链设计模式和双链责任链设计模式的区别


概述

一、行为设计模式

行为设计模式是设计模式的一种类型。该类型的设计模式关注的重点在于对象的行为(通信和交互),而非对象的创建方式。较为常见的行为设计模式有:观察者模式、策略模式、命令模式、责任链模式等。优点是减少了对象之间的耦合度

二、责任链模式

请求可能被一个对象(或处理器)或者多个相似的对象(或处理器)处理。责任链模式将多个对象串成一条链,使得请求沿着一条链传递,直到有一个对象能够处理该请求。由此看来,每个对象都有机会处理请求,所以这种模式使得请求的发送者和对象之间的耦合度降低,从而提高了代码的扩展性和可维护性。

优点

  • 使请求的发送者和请求的处理对象(处理器)耦合度降低。
  • 动态调整处理对象,可以根据需求新增,删除责任链上的对象,也可以灵活定义对象在链上的排列顺序。

缺点

  • 责任链过长可能会使得处理请求的速度变慢,影响性能。
  • 可能存在无法处理请求的情况。

三、单向责任链模式和双向责任链模式的区别

责任链模式将多个对象串成一条链,因此有了前驱对象和后继对象。其中:

单向责任链模式双向责任链模式
责任范围只能将请求传递给链上的下一个对象。能将请求传递给链上的任意对象。
优点实现简单,容易维护。支持请求的回溯和撤销,处理请求更灵活。
缺点只适用于简单的顺序传递请求。实现复杂,不易维护。需要更多的内存空间。

四、使用场景

  • 多个对象处理同一个请求时存在优先级关系。
  • 在不同的时间处理不同的部分。
  • 处理同一个请求的多个对象可以被动态改变。

五、列举责任链模式在成熟的框架中的应用

  • Java Servlet API中的Filter过滤器链。
  • Spring Framework中的拦截器链(Interceptor Chain)。
  • Netty中的ChannelHandler链。

实现

单向设计模式

需求

员工提交报销单申请报销,其中:

  1. 1000元(含)以下由直接主管审批。
  2. 1000元以上5000元(含)以下由部门经理审批。
  3. 5000元以上由总裁批准。

代码

处理器类

package com.ctx.chain.one;

import java.math.BigDecimal;

// CEO处理器
public class CEOHandler extends ExpenseHandler {
    // 5000元以上的报销由CEO处理
    private static final BigDecimal MINIMUM_APPROVAL_AMOUNT = new BigDecimal(5000);

    @Override
    public void handleExpense(BigDecimal amount) {
        if (amount.compareTo(MINIMUM_APPROVAL_AMOUNT) > 0) {
            System.out.println("CEO审批通过,报销金额为:" + amount);
        } else {
            System.out.println("报销金额太小,不需要CEO审批,报销金额为:" + amount);
        }
    }
}
package com.ctx.chain.one;

import java.math.BigDecimal;

// 部门经理处理器
public class DepartmentManagerHandler extends ExpenseHandler {
    // 1000元以上5000元(含)以下的报销由部门经理处理
    private static final BigDecimal MAXIMUM_APPROVAL_AMOUNT = new BigDecimal(5000);
    private static final BigDecimal MINIMUM_APPROVAL_AMOUNT = new BigDecimal(1000);

    @Override
    public void handleExpense(BigDecimal amount) {
        if (amount.compareTo(MINIMUM_APPROVAL_AMOUNT) > 0 && amount.compareTo(MAXIMUM_APPROVAL_AMOUNT) <= 0) {
            System.out.println("部门经理审批通过,报销金额为:" + amount);
        } else {
            successor.handleExpense(amount);
        }
    }
}
package com.ctx.chain.one;

import java.math.BigDecimal;

// 直接主管处理器
public class DirectSupervisorHandler extends ExpenseHandler {
    // 1000元(含)以下的报销由直接主管处理
    private static final BigDecimal MAXIMUM_APPROVAL_AMOUNT = new BigDecimal(1000);

    @Override
    public void handleExpense(BigDecimal amount) {
        if (amount.compareTo(MAXIMUM_APPROVAL_AMOUNT) <= 0) {
            System.out.println("直接主管审批通过,报销金额为:" + amount);
        } else {
            successor.handleExpense(amount);
        }
    }
}

处理器抽象类 

package com.ctx.chain.one;

import java.math.BigDecimal;

// 责任链模式中的抽象处理器
public abstract class ExpenseHandler {
    protected ExpenseHandler successor;

    // 设置下一个处理器
    public void setSuccessor(ExpenseHandler successor) {
        this.successor = successor;
    }

    // 处理报销请求的方法
    public abstract void handleExpense(BigDecimal amount);

}

调用类 

package com.ctx.chain.one;

import java.math.BigDecimal;
//调用类
public class Test {
    public static void main(String[] args) {
        ExpenseHandler directSupervisorHandler = new DirectSupervisorHandler();
        ExpenseHandler departmentManagerHandler = new DepartmentManagerHandler();
        ExpenseHandler ceoHandler = new CEOHandler();

        directSupervisorHandler.setSuccessor(departmentManagerHandler);
        departmentManagerHandler.setSuccessor(ceoHandler);

        BigDecimal expenseAmount1 = new BigDecimal(500);
        BigDecimal expenseAmount2 = new BigDecimal(1500);
        BigDecimal expenseAmount3 = new BigDecimal(6000);

        directSupervisorHandler.handleExpense(expenseAmount1);
        directSupervisorHandler.handleExpense(expenseAmount2);
        directSupervisorHandler.handleExpense(expenseAmount3);
    }
}

双向设计模式

需求

以受理用户投诉为案例,其中:

  1. 用户发起投诉,客服受理,客服可以选择:驳回、指派给运维人员,已解决。
  2. 运维人员处理投诉,可以选择:已解决,指派给运维主管。
  3. 运维主管处理投诉,可以选择:已解决,未解决。且不管是否解决,该投诉会下发至部门经理。
  4. 部门经理处理投诉,可以选择:满意,不满意。不满意则驳回至运维主管,满意则下发至客服。

需求流程图 

代码

投诉实体类

package com.ctx.chain.two;
public class Complaint {
    private String id;
    private String content;
    private String status;

    public Complaint(String id ,String content,String status) {
        setId(id);
        setContent(content);
        setStatus(status);
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

处理器抽象类

package com.ctx.chain.two;

public abstract class ComplaintHandler {
    protected String name;                   //处理器名称
    protected ComplaintHandler prevHandler;  //前一个处理器
    protected ComplaintHandler nextHandler;  //后一个处理器

    public ComplaintHandler(String name) {
        this.name = name;
    }
    public ComplaintHandler() {
    }
    public void setPrevHandler(ComplaintHandler prevHandler) {
        this.prevHandler = prevHandler;
    }

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

    public abstract void handleComplaint(Complaint complaint);    //处理投诉的抽象方法
}

处理器类

package com.ctx.chain.two.handler;

import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;

import java.util.Scanner;

/**
 * 客服
 */
public class CustomerServiceHandler extends ComplaintHandler {

    public CustomerServiceHandler(String name) {
        super(name);
    }
    public CustomerServiceHandler() {
        super();
    }

    @Override
    public void handleComplaint(Complaint complaint) {
        System.out.println("客服接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent());
        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择操作:1.驳回,2.指派运维人员,3.已解决。");
        int choice = scanner.nextInt();
        switch (choice) {
            case 1:
                complaint.setStatus("已驳回");
                System.out.println("投诉已驳回");
                break;
            case 2:
                System.out.println("请选择运维人员:1.张三,2.李四");
                int handlerChoice = scanner.nextInt();
                if (handlerChoice == 1) {
                    this.nextHandler = new OperatorHandler("张三");
                    this.nextHandler.setPrevHandler(this);
                } else if (handlerChoice == 2) {
                    this.nextHandler = new OperatorHandler("李四");
                    this.nextHandler.setPrevHandler(this);
                }
                this.nextHandler.handleComplaint(complaint);
                break;
            case 3:
                complaint.setStatus("已解决");
                System.out.println("投诉已解决");
                break;
            default:
                System.out.println("无效操作");
                break;
        }
    }
}
package com.ctx.chain.two.handler;

import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;

import java.util.Scanner;

/**
 * 部门经理
 */
public class DepartmentManagerHandler extends ComplaintHandler {

    public DepartmentManagerHandler(String name) {
        super(name);
    }

    public DepartmentManagerHandler() {
        super();
    }

    @Override
    public void handleComplaint(Complaint complaint) {
        System.out.println("部门经理" + this.name + "接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent()+"问题:"+complaint.getStatus());
        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择处理意见:1.满意,2.不满意");
        int choice = scanner.nextInt();
        switch (choice) {
            case 1:
                complaint.setStatus("已处理");
                System.out.println("处理意见已派发给客服");
                this.nextHandler = new CustomerServiceHandler();
                this.nextHandler.handleComplaint(complaint);
                break;
            case 2:
                complaint.setStatus("驳回");
                System.out.println("处理意见已驳回给运维主管");
                this.prevHandler.handleComplaint(complaint);
                break;
            default:
                System.out.println("无效操作");
                break;
        }
    }
}
package com.ctx.chain.two.handler;

import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;

import java.util.Scanner;

/**
 * 运维人员
 */
public class OperatorHandler extends ComplaintHandler {

    public OperatorHandler(String name) {
        super(name);
    }

    public OperatorHandler() {
        super();
    }

    @Override
    public void handleComplaint(Complaint complaint) {
        System.out.println("运维人员" + this.name + "接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent());
        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择操作:1.解决,2.转交给主管");
        int choice = scanner.nextInt();
        switch (choice) {
            case 1:
                complaint.setStatus("已解决");
                System.out.println("投诉已解决");
                this.prevHandler.handleComplaint(complaint);
                break;
            case 2:
                this.nextHandler = new SupervisorHandler("主管");
                //设置:运维主管的前驱处理器是运维人员
                this.nextHandler.setPrevHandler(this);
                this.nextHandler.handleComplaint(complaint);
                break;
            default:
                System.out.println("无效操作");
                break;
        }
    }
}
package com.ctx.chain.two.handler;

import com.ctx.chain.two.Complaint;
import com.ctx.chain.two.ComplaintHandler;

import java.util.Scanner;

/**
 * 运维主管
 */
public class SupervisorHandler extends ComplaintHandler {

    public SupervisorHandler(String name) {
        super(name);
    }

    public SupervisorHandler() {
        super();
    }

    @Override
    public void handleComplaint(Complaint complaint) {
        System.out.println("运维主管" + this.name + "接收到投诉,编号为" + complaint.getId() + ",内容为" + complaint.getContent());
        //this.nextHandler = new DepartmentManagerHandler();
        //this.nextHandler.setPrevHandler(this);
        //this.nextHandler.handleComplaint(complaint);

        Scanner scanner = new Scanner(System.in);
        System.out.println("请选择操作:1.解决,2.转交给部门经理。");
        int choice = scanner.nextInt();
        switch (choice) {
            case 1:
                complaint.setStatus("已解决");
                System.out.println("投诉已解决");
                this.nextHandler = new DepartmentManagerHandler("陈天相");
                //设置:部门经理的前驱处理器是运维主管
                this.nextHandler.setPrevHandler(this);
                nextHandler.handleComplaint(complaint);
                break;
            case 2:
                complaint.setStatus("未解决");
                System.out.println("投诉未解决");
                this.nextHandler = new DepartmentManagerHandler("陈天相");
                //设置:部门经理的前驱处理器是运维主管
                this.nextHandler.setPrevHandler(this);
                nextHandler.handleComplaint(complaint);
                break;
            default:
                System.out.println("无效操作");
                break;
        }
    }
}

调用类

package com.ctx.chain.two;

import com.ctx.chain.two.handler.CustomerServiceHandler;
import com.ctx.chain.two.handler.DepartmentManagerHandler;
import com.ctx.chain.two.handler.OperatorHandler;
import com.ctx.chain.two.handler.SupervisorHandler;

public class Test {
    public static void main(String[] args) {
        Complaint complaint = new Complaint("1","网络不稳定","待处理");

        ComplaintHandler customerServiceHandler = new CustomerServiceHandler();
        ComplaintHandler operatorHandler = new OperatorHandler();
        ComplaintHandler supervisorHandler = new SupervisorHandler();
        ComplaintHandler departmentManagerHandler = new DepartmentManagerHandler();

        customerServiceHandler.setNextHandler(operatorHandler);
        operatorHandler.setNextHandler(supervisorHandler);
        supervisorHandler.setNextHandler(supervisorHandler);
        departmentManagerHandler.setNextHandler(customerServiceHandler);

        customerServiceHandler.handleComplaint(complaint);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/459004.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

three.js车辆可视化教程-完整0到1

概述 如有不明白的可以加QQ&#xff1a;2354528292&#xff1b;wx: aichitudousien 更多教学视频请访问&#xff1a;https://space.bilibili.com/236087412 详细教学请到上方视频链接访问&#xff0c;总共3个多小时的教学~ Three.js车展系统 搭建开发环境 使用的开发框架是vu…

计算机程序安装及使用须知_kaic

安装及使用须知 1 数据库建模程序的使用 本文件夹中的“PowerDesigner建模”目录下包含三个可运行文件TMS1.cdm&#xff0c;TMS.cdm&#xff0c;TMS.pdm分别为TMS系统的实体关系简图、实体关系图和数据库模型&#xff0c;使用PowerDesigner集成开发环境打开任意一个文件即可运…

第二节 ogre sdk 配置使用

上一节&#xff0c;我们介绍过了ogre源码的编译学习&#xff0c;在实际项目中&#xff0c;我们并不需要如此复杂的编译安装过程&#xff0c;可以直接使用官网提供的sdk库进行项目环境配置。下面简单介绍下配置过程。 一 OgreSDK下载 https://dl.cloudsmith.io/public/ogrecav…

Know-Evolve: Deep Temporal Reasoning for Dynamic Knowledge Graphs

Know-Evolve: Deep Temporal Reasoning for Dynamic Knowledge Graphs Rakshit Trivedi 1 Hanjun Dai 1 Yichen Wang 1 Le Song 1 知识背景 Temporal Knowledge Graph : facts occur,recur or evolve over time in these graphs,and each edge in the graphs have temporal …

FPGA基于XDMA实现PCIE X8视频采集HDMI输出 提供工程源码和QT上位机程序和技术支持

目录 1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案5、vivado工程详解6、驱动安装7、QT上位机软件8、上板调试验证9、福利&#xff1a;工程代码的获取 1、前言 PCIE&#xff08;PCI Express&#xff09;采用了目前业内流行的点对点串行连接&#xff0c;比起 PC…

【翻译一下官方文档】之uniapp的数据缓存

uni.setStorage(OBJECT) setstorage | uni-app官网 uni.setStorage(OBJECT) 将数据存储在本地缓存中指定的 key 中&#xff0c;会覆盖掉原来该 key 对应的内容&#xff0c;这是一个异步接口。 参数名类型必填说明keyString是本地缓存中的指定的 keydataAny是需要存储的内容&am…

git workflow

git workflow 讲一下常用的 workflow&#xff0c;这个主要是根据自己个人工作经验&#xff0c;每个项目在实践上总会有些许的不同&#xff0c;求同存异。 单分支工作 最糟糕的 workflow 是所有人全都在 main/master 上干活&#xff0c;如果只是两三个人的 team 可能还能存活…

忆暖行动|“四方食事,不过人间一碗烟火”

四方食事,不过人间一碗烟火 外婆&#xff0c;如果要您选择一个乡村很有代表的食物&#xff0c;您会选择什么&#xff1f; 当然是米饭&#xff0c;人要吃饭&#xff0c;没有米饭就没有力气劳作&#xff0c;而且大米还能做很多美食&#xff0c;比如米饼&#xff0c;米糕&#x…

亚马逊测评有哪些误解?

亚马逊平台是全球性的互联网电商网络平台&#xff0c;成立至今&#xff0c;平台站点覆盖了全球多个国家&#xff0c;各个地区之间的商品交易也变得更加频繁&#xff0c;随着平台商家增多&#xff0c;为了提高自身排名&#xff0c;越来越多的商家开始找人为他们的店铺和产品进行…

Git比较好用的一些操作

git stash 可以缓存一些修改&#xff0c;不用做提交。例如当前分支做了修改&#xff0c;不想提交&#xff0c;有需要切换分支时候。 常用命令&#xff1a; git stash list&#xff1a;查看缓存列表 git stash list git stash save “备注信息”: 缓存当前分支所有修改 git …

快乐数链表篇

编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。 如果这个过程 结果为 1&#xff…

【数据库数据恢复】ORACLE常见数据灾难的数据恢复可能性分析

Oracle数据库常见数据灾难&#xff1a; 1、ORACLE数据库无法启动或无法正常运行。 2、ORACLE ASM存储破坏。 3、ORACLE数据库数据文件丢失。 4、ORACLE数据库数据文件损坏。 5、ORACLE DUMP文件损坏。 Oracle数据库常见数据灾难的数据恢复可能性分析&#xff1a; 1、O…

正则表达式 - 简单模式匹配

目录 一、测试数据 二、简单模式匹配 1. 匹配字面值 2. 匹配数字和非数字字符 3. 匹配单词与非单词字符 4. 匹配空白字符 5. 匹配任意字符 6. 匹配单词边界 7. 匹配零个或多个字符 8. 单行模式与多行模式 一、测试数据 这里所用文本是《学习正则表达式》这本书带的&a…

统计学习方法第二章——感知机

x.1 前言 perceptron感知机是二分类的线性分类模型&#xff0c;输入为实例的特征向量&#xff0c;输出为实例类别(取-1&#xff0c;1)。perceptron旨在求出将训练数据进行线性划分的分离超平面&#xff0c;属于classification判别模型&#xff0c;策略为基于误分类的损失函数&…

MCU短按长按的功能

.外设&#xff1a;一个io口、一个定时器。 为了降低上手的门槛&#xff0c;本文仅使用一个IO口作演示。 实现思路 使用定时器&#xff0c;定时20ms来读取简化的按键状态机。 这里简化了状态机&#xff0c;大家只需明白三个概念。 状态&#xff1a;数量为有限个&#xff0c;记…

css初入门:网页布局之网格布局-grid

文章目录 网格布局-grid1、设置网格布局2、网格布局介绍3、网格容器grid-template-columns属性grid-template-rows 属性justify-content 属性justify-items属性align-content 属性 4、网格项目grid-column-start、grid-column-start、grid-column属性grid-row-start、grid-row-…

ChatGPT来了,必须紧跟时代潮流!

大家好&#xff0c;我是瓜叔。 正如标题所示&#xff0c;最近几周令人难以置信的兴奋。几乎每天都有surprise的新AI产品发布&#xff0c;特别是ChatGPT-4和AI绘画。这是一种科幻即将成为现实的感觉。例如&#xff0c;看看下面的网络图像&#xff0c;它是由AI生成的。当我看到它…

我的HackerOne漏洞赏金平台漏洞挖掘流程

简介 高强度在hackerone平台挖了一周的漏洞&#xff0c;在这里分享一下经验 选定目标 hackerone有两种src&#xff0c;一种是给钱的&#xff0c;一种是免费的&#xff0c;我一般都是选的有钱的去挖 假如我选择了这个作为今天的挖洞目标 首先需要往下滑&#xff0c;看他不收…

银行系统【GUI/Swing+MySQL】(Java课设)

系统类型 Swing窗口类型Mysql数据库存储数据 使用范围 适合作为Java课设&#xff01;&#xff01;&#xff01; 部署环境 jdk1.8Mysql8.0Idea或eclipsejdbc 运行效果 ​​​​​​​ 本系统源码地址&#xff1a;​​​​​​​https://download.csdn.net/download/qq_50…

科大讯飞的2022:夯实“根据地”业务,以技术创新点燃大模型产业落地的“星星之火”...

‍数据智能产业创新服务媒体 ——聚焦数智 改变商业 4月20日晚&#xff0c;科大讯飞正式公布2022年度及2023年度第一季度业绩报告。财报数据显示&#xff0c;公司2022年度实现营业收入188.20亿元&#xff0c;同比增长2.77%&#xff0c;实现毛利76.84亿元&#xff0c;较上年增长…