当前位置: 首页 > news >正文

责任链模式如何减少模块之间的耦合

责任链模式如何减少模块之间的耦合

在复杂的软件系统中,模块之间的耦合是一个常见的问题。高耦合的代码不仅增加了维护成本,还会导致系统的扩展性和灵活性受限。当我们需要为不同的请求设计灵活的处理逻辑时,传统的硬编码方式会将请求的发送者与处理逻辑紧密绑定,导致代码难以适应需求的变化。在这种背景下,责任链模式提供了一种优雅的解决方案。

责任链模式通过将请求沿着一个“责任链”传递,使多个对象都有机会处理该请求。请求的发送者不需要知道谁会处理它,处理逻辑由链上的处理者动态决定。这种模式将“请求的发送”与“请求的处理”解耦,每个处理者专注于自己的职责,避免了模块间的直接依赖。例如,在一个企业审批流程中,不同级别的审批人员可能会处理不同类型的请求,而使用责任链模式,审批流程的动态调整只需要改变链条的顺序,无需修改核心业务逻辑。

责任链模式的定义

1. 核心定义

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它通过将请求沿着一个职责链(责任链)传递,使得多个对象都有机会处理该请求,而请求的发送者不需要明确指定接收者。请求会沿链条依次传递,直到某个对象处理它或者链的末尾。

2. 核心思想
  • 将请求的发送者和处理者解耦,使得发送者不需要关心处理者的具体实现。
  • 责任链由多个处理者组成,每个处理者负责特定的任务或条件判断,当当前处理者无法处理请求时,它将请求转交给下一个处理者。
3. 责任链模式的组成
  1. 抽象处理者(Handler)
    • 定义一个处理请求的接口或抽象类。
    • 提供设置下一个处理者的功能。
  1. 具体处理者(ConcreteHandler)
    • 实现处理逻辑。
    • 决定是否自己处理请求或者将请求传递给下一个处理者。
  1. 客户端(Client)
    • 创建请求并将其提交到责任链的起点。
4. 责任链模式的作用
  • 解耦发送者与接收者:请求发送者不需要知道谁会处理请求,增强代码灵活性。
  • 动态职责分配:通过调整责任链中的处理者顺序,可以动态改变请求的处理流程。
5. 示例场景
  • 日志处理系统:日志按照不同的级别(DEBUG、INFO、WARN、ERROR)由不同的处理器处理。
  • 权限校验:请求需要通过一系列权限校验节点,逐一验证。
  • 审批流系统:如企业中的多级审批流程,不同级别的请求由不同角色处理。

责任链模式的结构

责任链模式的核心在于将一组具有相同接口的处理者(Handler)链接成一个链条,使请求能够沿着链条传递,直到被某个处理者处理或到达链尾。其结构设计强调模块间的职责分离与动态组合。

1. 抽象处理者(Handler)
  • 定义职责链中的基础元素
    抽象处理者是责任链的核心接口或抽象类,定义了一个处理请求的接口以及设置或调用下一个处理者的方法。
  • 职责
    • 提供统一的方法来处理请求。
    • 保存下一个处理者的引用,形成链式结构。
    • 实现链的递归调用机制。
  • 关键方法

示例代码

public abstract class Handler {protected Handler next; // 下一个处理者public void setNext(Handler next) {this.next = next;}public abstract void handleRequest(String request);
}
    • handleRequest(): 接收并处理请求。
    • setNextHandler(Handler next): 设置链条中的下一个处理者。
2. 具体处理者(ConcreteHandler)
  • 实现具体的处理逻辑
    每个具体处理者负责处理特定类型的请求,或者决定是否将请求传递给下一个处理者。
  • 职责
    • 对请求的条件进行判断。
    • 实现具体的业务逻辑。
    • 在不能处理时,将请求传递给下一个处理者。
  • 设计要点

示例代码

public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("Handler A 处理了请求");} else if (next != null) {next.handleRequest(request);}}
}
    • 每个处理者只专注于自己的职责,确保单一职责原则。
    • 可通过继承抽象处理者类实现统一的处理流程。
3. 客户端(Client)
  • 发起请求并构建责任链
    客户端是责任链的入口,负责创建具体的处理者对象并将它们串联成链。
  • 职责
    • 创建责任链的处理者实例。
    • 设置链条顺序。
    • 向责任链发送请求。
  • 灵活性
    客户端可以根据需要动态调整链条的处理顺序或新增处理者。示例代码
public class Client {public static void main(String[] args) {// 创建处理者Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();// 构建责任链handlerA.setNext(handlerB);// 发起请求handlerA.handleRequest("A");handlerA.handleRequest("B");}
}
4. 结构图

以下是责任链模式的典型 UML 图结构:

  • 抽象处理者位于链条的顶端,定义了统一的接口。
  • 具体处理者通过继承抽象处理者实现具体逻辑,链接形成链条。
  • 客户端只需要向链条的入口发送请求,后续由链条自动完成处理。
Client --> Handler (抽象)| +--> ConcreteHandlerA (具体)|+--> ConcreteHandlerB (具体)
5. 结构的优点
  1. 请求与处理者解耦:请求的发送者不需要知道具体的处理者。
  2. 职责分离:每个处理者只关心自己的职责,代码更加模块化。
  3. 动态组合:可以动态调整链条的处理逻辑和顺序,符合开闭原则。
6. 结构的缺点
  1. 性能问题:链条过长可能导致处理效率降低。
  2. 调试复杂性:请求传递过程中,调试和跟踪可能较为困难。

责任链模式如何减少模块之间的耦合

责任链模式通过将请求的发送者与请求的处理者解耦,显著降低模块之间的直接依赖,从而实现高内聚、低耦合的设计。以下从多个方面深入分析责任链模式如何减少模块之间的耦合。

1. 请求发送者与处理者的解耦
  • 传统方式的问题
    在传统设计中,请求发送者需要直接调用处理者的逻辑。这种方式将请求发送者与具体处理逻辑绑定在一起,增加了系统的复杂性和维护成本。当处理逻辑变化时,发送者也需要修改,导致耦合度较高。
  • 责任链模式的解决方案
    • 请求发送者只需将请求交给责任链的起点,而不需要知道链上的具体处理者是谁以及它们的处理顺序。
    • 每个处理者独立判断是否处理请求,或将请求传递给下一个处理者。
    • 通过统一的接口或抽象类,处理者对外表现为一个整体,从而实现发送者与处理者的解耦。

示例:一个客户请求的审批流程可能包含多个级别(部门经理、人事部门、财务部门),发送者不需要知道具体由哪个级别处理,只需提交请求给责任链的起点即可。

2. 单一职责原则的实现
  • 传统设计的耦合问题
    在没有责任链模式的情况下,一个模块可能承担多个职责,例如既要接收请求,又要执行特定逻辑,还要处理异常情况。这种设计容易造成代码复杂、维护困难。
  • 责任链的优化
    • 通过将处理逻辑分散到链条的多个节点,每个节点只关注自身的职责,符合单一职责原则。
    • 处理逻辑的分离使每个模块独立运作,相互之间不受影响。

示例:在权限管理系统中,不同角色的权限校验可以被拆分为独立的处理者,如管理员、普通用户和游客。每个处理者只关注与自己角色相关的逻辑。

3. 灵活的扩展能力
  • 传统设计的刚性
    如果需要添加新的处理逻辑,传统方式通常需要修改请求发送者或其他模块的代码,导致系统扩展性差,违背开闭原则。
  • 责任链模式的动态性
    • 责任链允许动态调整链条中的处理者顺序或添加新处理者,而无需修改发送者和其他处理者的代码。
    • 新的处理者可以通过实现统一的接口,轻松加入到现有责任链中。

示例:在支付系统中,可以动态添加新的支付方式(如信用卡、PayPal、微信支付等),无需修改现有代码。

4. 可插拔的链条设计
  • 传统设计的僵化性
    当多个模块的逻辑紧密耦合时,新增或移除某个功能需要大规模修改代码,容易引入错误。
  • 责任链的模块化
    • 通过链条设计,处理者模块可以独立插拔,不会影响其他模块。
    • 如果需要临时禁用某个处理者,可以简单地从链条中移除,而不破坏整体结构。

示例:在日志系统中,可以动态调整日志的处理链条,例如新增文件记录或移除控制台输出的功能。

5. 责任链与面向接口编程
  • 传统的强耦合问题
    模块之间通常依赖于具体实现,导致修改或替换某个模块时,需要连带修改其他模块的代码。
  • 责任链的接口化设计
    • 责任链模式采用面向接口编程,处理者通过抽象接口进行定义。
    • 模块间只需依赖接口,具体实现可以随时替换。

示例:在请求校验系统中,可以通过统一的校验接口定义多种校验规则(如格式校验、权限校验、数据完整性校验),链条的实现可以根据业务需求动态变化。

6. 减少双向依赖
  • 传统设计中的双向耦合问题:请求发送者往往需要依赖处理者的逻辑,处理者可能也会依赖发送者的状态,从而形成双向依赖。
  • 责任链的单向传递
    • 请求在责任链中单向传递,发送者与处理者之间没有直接关联。
    • 处理者之间也仅通过“链条引用”联系,不需要了解彼此的具体实现。

示例:在异常处理系统中,不同类型的异常由不同模块处理,责任链可以按类型逐级传递,无需模块间的双向依赖。

实现步骤

以下是实现责任链模式的关键步骤,详细说明了每一步的设计思路和注意事项:

1. 定义处理请求的抽象接口
  • 目标:定义一个通用的接口(或抽象类),用于规范所有处理者的行为。
  • 内容
    • 接口中包含一个 handleRequest 方法,表示处理请求的核心逻辑。
    • 定义一个指向下一个处理者的引用,形成链条结构。

代码示例

public abstract class Handler {protected Handler nextHandler;// 设置下一个处理者public void setNextHandler(Handler nextHandler) {this.nextHandler = nextHandler;}// 抽象的请求处理方法public abstract void handleRequest(String request);
}
2. 创建具体的处理者
  • 目标:为每个具体的处理逻辑实现一个独立的处理者类。
  • 内容
    • 实现抽象接口的 handleRequest 方法。
    • 在方法中决定是否处理当前请求,如果不处理,则将请求传递给下一个处理者。

代码示例

public class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(String request) {if ("A".equals(request)) {System.out.println("Handler A 处理了请求: " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}public class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(String request) {if ("B".equals(request)) {System.out.println("Handler B 处理了请求: " + request);} else if (nextHandler != null) {nextHandler.handleRequest(request);}}
}
3. 构建责任链
  • 目标:将各个处理者按照业务逻辑顺序连接起来,形成一条责任链。
  • 内容
    • 创建多个处理者实例。
    • 设置每个处理者的下一个处理者引用。

代码示例

public class ChainBuilder {public static Handler buildChain() {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();// 构建链条handlerA.setNextHandler(handlerB);return handlerA; // 返回链条的起点}
}
4. 发送请求并启动处理
  • 目标:通过责任链的起点发送请求,触发链条的处理流程。
  • 内容
    • 请求会从链条起点依次传递到下一个处理者,直到被处理或到达链条末端。

代码示例

public class Client {public static void main(String[] args) {// 构建责任链Handler chain = ChainBuilder.buildChain();// 测试不同的请求chain.handleRequest("A"); // Handler A 处理chain.handleRequest("B"); // Handler B 处理chain.handleRequest("C"); // 无人处理}
}

输出结果:

Handler A 处理了请求: A
Handler B 处理了请求: B
5. 动态扩展责任链
  • 目标:通过链条的灵活性,实现动态扩展或调整链条的处理者。
  • 内容
    • 新增处理者时,只需实现接口并将其添加到链条中,无需修改现有代码。
    • 调整链条顺序时,只需更改 setNextHandler 的调用顺序。

示例场景
如果需要新增一个 ConcreteHandlerC,只需:

Handler handlerC = new ConcreteHandlerC();
handlerB.setNextHandler(handlerC);
6. 优化责任链设计(可选)
  • 目标:增强责任链的灵活性和性能。
  • 优化措施
    • 链条终止机制:在处理过程中加入终止条件,避免不必要的链条遍历。
if (conditionMet) {return; // 终止处理
}
    • 责任链的动态配置:通过配置文件或外部数据定义责任链,提升灵活性。
    • 并行责任链:对于性能要求较高的场景,可考虑让部分责任链并行处理。

责任链模式的优点

责任链模式通过将请求的处理职责分离到多个对象中,使系统具备高度的灵活性和可扩展性。

1. 降低模块之间的耦合
  • 请求的发送者与接收者解耦,发送者无需知道具体是哪个对象处理请求。
  • 处理者之间的职责划分清晰,链条的实现细节对调用方透明。

示例:客户端只需要将请求交给链的起点,无需了解链条中具体有哪些处理者或每个处理者的实现逻辑。

2. 提高系统的灵活性
  • 可以根据需求动态地调整链条中的处理者或链条顺序,而不需要修改已有代码。
  • 责任链可以通过组合模式实现灵活的运行时行为。

示例:新增一个处理者,只需实现相应接口并将其插入链条,不影响其他处理者。

3. 符合开闭原则
  • 新增或修改处理逻辑时,可以通过新增处理者或调整链条结构实现,而无需修改现有处理者代码。
  • 责任链的实现避免了复杂的 if-elseswitch 判断逻辑。

示例:添加新类型的请求处理逻辑,只需增加一个处理者类,而无需修改原有代码。

4. 易于扩展和维护
  • 每个处理者只专注于其职责范围内的逻辑,实现了职责单一化,便于开发和维护。
  • 代码的可读性和可维护性增强,减少了因逻辑交叉导致的复杂度。

示例:在审批系统中,每级审批规则可以独立实现,便于后续的规则更新。

5. 支持请求的多级处理
  • 请求可以沿着责任链被多个处理者依次处理,满足复杂业务场景的需求。
  • 处理者可以选择是否将请求传递给下一个处理者,提供了灵活的控制机制。

示例:在订单处理系统中,订单可以经过验证、审批、扣款等多个阶段,每个阶段由不同的处理者负责。

6. 增强代码的复用性
  • 通过模块化设计,责任链中的处理者可以在其他链条中复用。
  • 统一的接口规范使得处理者的复用性更高,适用于不同的业务场景。

示例:日志记录的处理模块可以在多个责任链中复用,如用户操作日志、系统错误日志等。

7. 灵活的终止机制
  • 责任链可以根据特定条件中断,避免不必要的处理流程,提高性能。
  • 终止机制可以避免无意义的链条遍历,从而优化系统效率。

示例:如果某处理者已经完全处理了请求,可以直接返回,避免请求继续传递。

8. 便于测试和调试
  • 每个处理者独立实现,可以单独测试其功能逻辑。
  • 链条的组合方式使得问题定位更加简单,可以通过逐步启用或禁用处理者快速找到问题来源。

示例:在调试责任链时,可以通过日志记录每个处理者是否接收或处理了请求,追踪问题。

适用场景

责任链模式非常适合解决多对象协作、职责动态分配的问题,尤其是在以下场景中具有显著优势:

1. 审批流程
  • 场景描述:在企业中,常见的审批流程通常有多个级别(如部门经理审批、总经理审批)。
  • 责任链作用:可以将每一级审批定义为责任链中的一个处理者,审批请求沿着链条传递,直至满足审批条件。
  • 示例:员工报销流程,部门经理审批不超过 5000 元,总经理审批不超过 20000 元,超过 20000 元需董事长审批。
2. 权限校验
  • 场景描述:在权限管理系统中,用户权限需要逐级检查。
  • 责任链作用:每个处理者负责校验一部分权限,链条终止于校验通过或权限不足。
  • 示例:一个用户的请求可能需要经过身份验证、角色验证、权限范围验证等。
3. 日志处理
  • 场景描述:系统中不同的日志需要不同的记录方式(如控制台输出、文件记录、远程服务器记录)。
  • 责任链作用:日志信息沿着链条传递,每个处理者判断是否需要处理。
  • 示例:调试日志记录到控制台,错误日志写入文件,关键错误日志上传到远程服务器。
4. 消息分发
  • 场景描述:系统接收到用户请求或事件后,需要根据消息类型将其分发到对应的处理模块。
  • 责任链作用:每个模块判断是否能处理该消息,如果不能处理则交给下一个模块。
  • 示例:在网络协议栈中,根据协议类型(如 TCP、UDP)选择不同的处理模块。
5. 命令处理系统
  • 场景描述:命令请求需要经过一系列模块处理,每个模块只处理自己关注的部分。
  • 责任链作用:将命令处理的逻辑分散到多个处理者,降低模块之间的耦合。
  • 示例:在游戏开发中,玩家的操作请求可能需要依次经过输入解析、权限校验、动作执行等多个阶段。
6. 动态规则引擎
  • 场景描述:业务规则可能会频繁调整,需要动态配置和扩展处理逻辑。
  • 责任链作用:每条规则可以作为一个处理者,动态组装成责任链,无需修改核心代码。
  • 示例:电子商务平台的优惠活动规则引擎,如满减、折扣、赠品规则依次生效。
7. 异常处理机制
  • 场景描述:系统中可能会发生不同级别的异常,需要逐层捕获并处理。
  • 责任链作用:每个处理者根据异常类型选择是否处理,未处理的异常传递到下一个处理者。
  • 示例:Java 中的异常处理机制(try-catch-finally),类似责任链的思想。
8. 过滤器链
  • 场景描述:对请求或数据进行一系列预处理操作(如校验、格式化、加密)。
  • 责任链作用:每个处理者完成特定的预处理任务,确保后续处理者接收到的请求符合要求。
  • 示例:在 Web 应用中,对请求数据执行参数校验、身份认证、日志记录等操作。
9. UI 事件处理
  • 场景描述:在图形用户界面(GUI)中,用户的点击、键盘输入等事件可能需要多个组件处理。
  • 责任链作用:事件沿着组件树传递,直至某个组件处理该事件。
  • 示例:Java Swing 或 Android 中的事件分发机制。
10. 职责动态分配
  • 场景描述:需要在运行时动态调整对象的职责范围。
  • 责任链作用:通过动态组合处理者,可以灵活改变链条的职责划分。
  • 示例:动态扩展一个电商订单的处理逻辑,例如新增库存检查环节。

       想获取更多高质量的Java技术文章?欢迎访问Java技术小馆官网,持续更新优质内容,助力技术成长

Java技术小馆官网https://www.yuque.com/jtostring

相关文章:

责任链模式如何减少模块之间的耦合

责任链模式如何减少模块之间的耦合 在复杂的软件系统中,模块之间的耦合是一个常见的问题。高耦合的代码不仅增加了维护成本,还会导致系统的扩展性和灵活性受限。当我们需要为不同的请求设计灵活的处理逻辑时,传统的硬编码方式会将请求的发送…...

Java面试:集合框架体系

一、ArrayList 1.数组(Array) 是一种用连续的内存空间存储相同数据类型数据的线性数据结构 数组如何获取其他元素的地址值? 寻址公式:a[i] baseAddress i * dataTypeSize baseAddress:数组的首地址dataTypeSize&am…...

【八股文】ArrayList和LinkedList的区别

先讲讲两者是如何实现的 ArrayList public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable {transient Object[] elementData; private int size; } 通过源码可以看出&#xff0c;ArrayLis…...

sentinel限流算法

限流算法&#xff1a;固定窗口算法、滑动时间窗口、令牌桶和漏桶这四种常见限流算法的原理&#xff1a; 限流算法原理 固定窗口&#xff1a; 固定窗口算法将时间划分为固定大小的窗口&#xff0c;并在每个窗口内限制请求的数量。在每个窗口开始时&#xff0c;计数器重置&#…...

Spring生态下的中台架构设计:如何构建可扩展业务系统?

一、中台战略的架构觉醒 在数字化转型的浪潮中,企业面临的核心矛盾日益凸显:前端业务的快速迭代需求与后端系统刚性架构之间的矛盾。中台架构的提出,本质上是对传统单体架构和过度微服务化的辩证扬弃。Spring生态以其模块化设计理念,恰好为中台建设提供了绝佳的技术土壤。…...

Project回调函数qsort②进阶应用

#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h>//库函数strcmp头文件 //使用qsort排序结构体 struct Stu { char name[20]; int age; }; //按照年龄排序 int cmp_stu_by_age(const void* e1,const void* e2) { return ((struc…...

【推荐项目】052-用水监控管理系统

052-用水监控管理系统 介绍 用水监控管理系统 springboot java vuejs jdk1.8 当然&#xff0c;以下是一个简洁的用水监控管理系统的功能模块划分&#xff0c;基于Spring Boot&#xff08;JDK 1.8&#xff09;后端和Vue.js前端&#xff1a; 用水监控管理系统功能模块 后端&…...

Hive SQL 精进系列:PERCENTILE_APPROX 搞定分位数

目录 一、引言二、percentile_approx 函数基础2.1 基本语法参数解释返回值简单示例 三、应用场景3.1 数据分析与报告3.2 数据清洗与异常值检测3.3 性能监控与优化 四、使用注意事项4.1 数据类型要求4.2 精度与性能平衡4.3 空值处理 五、总结 一、引言 百分位数作为一种常用的统…...

使用Hbuilder发布小程序显示发布失败?

接受了一个新uniapp项目 但是在Hbuilder中发行报错 小程序发行失败 试了几次还是不行 写代码的人也走了&#xff0c;头疼。 不用Hbuilder小程序的主包体积又太大哎 开发工具无法上传~ 后来想看一下 这个发布失败到底有没有生成打包好的文件 如果生成了可以试一下 直接导入到微信…...

甲骨文找回二次验证的方法(超简单)

因为更换手机丢失了二次验证。 然后给客服沟通&#xff0c;获得了找到二次验证的办法&#xff0c;希望对你有用。 1、登录到账号登陆界面&#xff0c;查看地址栏当中自己的IDCE地址&#xff08;yourIDCS_Stripe_here&#xff09;部分&#xff0c;并复制。 https://idcs-yourID…...

Tcp网络通信的基本流程梳理

先来一张经典的流程图 接下介绍一下大概流程&#xff0c;各个函数的参数大家自己去了解加深一下印象 服务端流程 1.创建套接字&#xff1a;使用 socket 函数创建一个套接字&#xff0c;这个套接字后续会被用于监听客户端的连接请求。 需要注意的是&#xff0c;服务端一般有俩…...

C++相关基础概念之入门讲解(上)

1. 命名空间 C中的命名空间&#xff08;namespace&#xff09;是用来避免命名冲突问题的一种机制。通过将类、函数、变量等封装在命名空间中&#xff0c;可以避免不同部分的代码中出现相同名称的冲突。在C中&#xff0c;可以使用namespace关键字来定义命名空间。 然后我们在调…...

Redis能否替代MySQL作为主数据库?深入解析两者的持久化差异与适用边界——基于AOF持久化与关系型数据库的对比

一、Redis的持久化机制与可靠性分析 ​AOF持久化原理与策略 Redis的AOF&#xff08;Append Only File&#xff09;通过记录所有写操作命令实现持久化&#xff0c;支持三种策略&#xff1a; ​**always模式**&#xff1a;每条命令执行后立即同步到磁盘&#xff0c;理论上数据丢失…...

Hive函数大全:从核心内置函数到自定义UDF实战指南(附详细案例与总结)

目录 背景‌一、Hive函数分类与核心函数表‌1. 内置函数分类‌2. 用户自定义函数(UDF)分类二、常用函数详解与实战案例‌1. 数学函数‌2. 字符串函数‌3. 窗口函数‌4. 自定义UDF实战‌三、总结与优化建议‌1. 核心总结2. 性能优化建议‌3. 常问问题背景‌ Hive作为Hadoop生…...

如何修改 Ubuntu 软件源(镜像源)

如何修改 Ubuntu 软件源&#xff08;镜像源&#xff09; 前言 在使用 Ubuntu 时&#xff0c;默认的软件源可能速度较慢&#xff0c;影响软件安装和系统更新的效率。我们可以通过修改 sources.list 文件或使用图形界面更换更快的镜像源&#xff0c;提升软件包管理的速度。 本…...

在Spring Boot项目中接入DeepSeek深度求索,感觉笨笨的呢

文章目录 引言1. 什么是DeepSeek&#xff1f;2. 准备工作2.1 注册DeepSeek账号 3.实战演示3.1 application增加DS配置3.2 编写service3.3 编写controller3.4 编写前端界面chat.html3.5 测试 总结 引言 在当今快速发展的数据驱动时代&#xff0c;企业越来越重视数据的价值。为了…...

AP AR

混淆矩阵 真实值正例真实值负例预测值正例TPFP预测值负例FNTN &#xff08;根据阈值预测&#xff09; P精确度计算&#xff1a;TP/(TPFP) R召回率计算&#xff1a;TP/(TPFN) AP 综合考虑P R 根据不同的阈值计算出不同的PR组合&#xff0c; 画出PR曲线&#xff0c;计算曲线…...

Vue 中的 MVVM、MVC 和 MVP 模式深度解析

文章目录 1. 模式概览与核心概念1.1 模式定义1.2 架构对比图 2. MVC 模式详解2.1 MVC 流程图2.2 Vue 中的 MVC 实现 3. MVP 模式详解3.1 MVP 流程图3.2 Vue 中的 MVP 实现 4. MVVM 模式详解4.1 MVVM 流程图4.2 Vue 中的 MVVM 实现 5. 模式对比分析5.1 职责对比5.2 通信方式对比…...

WVP前后端部署

使用默认的构建&#xff0c;能够直接访问18080&#xff0c;我以为二者是一起的。实际上这不影响前后端分离。 前端服务器 构建war之后&#xff0c;部署到另外一台机器上&#xff0c;比如使用apache2。 后端服务器 修改src/main/resources/static/static/js/config.js&#…...

VSTO(C#)Excel开发9:处理格式和字体

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…...

蓝耘MaaS平台:阿里QWQ应用拓展与调参实践

摘要&#xff1a;本文深入探讨了蓝耘MaaS平台与阿里QWQ模型的结合&#xff0c;从平台架构、模型特点到应用拓展和调参实践进行了全面分析。蓝耘平台凭借其强大的算力支持、弹性资源调度和全栈服务&#xff0c;为QWQ模型的高效部署提供了理想环境。通过细化语义描述、调整推理参…...

【统计学相关笔记】2. 多元正态的Cochran定理

fisher 引理 如何说明一个线性变换和二次型独立&#xff1a; 二次型矩阵和线性变换阵乘积0即可。...

Vuex 基础概念与环境搭建

Vuex 是实现数据集中式状态管理的插件。所有组件共享 Vuex 中的数据&#xff0c;当任意组件修改数据时&#xff0c;其他组件会同步更新。与全局事件总线的区别在于&#xff1a; 全局事件总线&#xff1a;数据传递但未真正共享Vuex&#xff1a;数据存储在中央仓库&#xff0c;实…...

使用 BookMarkHub 插件进行书签同步

前言: 通过 BookMarkHub 插件&#xff0c;你可以方便地将书签同步到 GitHub Gist&#xff0c;实现跨设备管理书签。以下是详细的步骤&#xff1a; 使用 BookMarkHub 插件进行书签同步 1. 安装 BookMarkHub 插件2. 获取 GitHub Token3. 获取 Gist ID4. 配置 BookMarkHub 插件5.完…...

用Lua脚本实现Redis原子操作

1. 环境准备 依赖&#xff1a;在pom.xml中添加Spring Data Redis&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>配置RedisTemplate&#…...

【算法】位运算

文章目录 1. 常见位运算总结&#xff08;图片包含五道算法题&#xff09;2. leetcode 面试题 01.01 判断字符是否唯一2.1 题目2.2 思路2.3 代码 3.leetcode 268. 丢失的数字3.1 题目3.2 思路3.3 代码 4. leetcode 371.两整数之和4.1 题目4.2 思路4.3 代码 5.leetcode 137.只出现…...

HTML块级元素和内联元素(简单易懂)

在HTML中&#xff0c;元素可以分为块级元素&#xff08;Block-level elements&#xff09;和内联元素&#xff08;Inline elements&#xff09;。这两类元素在页面布局和样式应用上有不同的特点和用途。 一、块级元素&#xff08;Block-level elements&#xff09; 1. 定义 …...

【论文精读】DifFace: Blind Face Restoration with Diffused Error Contraction

文章目录 0.前言1.当前问题2.怎么解决问题3.具体做法(Method)3.1 受什么的启发&#xff1f;(Motivation)3.2具体的模型设计(Design)3.3 整体算法 4.实验效果4.1 Synthetic(CelebA-Test)4.2 Real World &#xff08;LFW, WebPhoto, and WIDER&#xff09; 0.前言 这篇文章是被 …...

[新能源]新能源汽车快充与慢充说明

接口示意图 慢充接口为交流充电口&#xff08;七孔&#xff09;&#xff0c;快充接口为直流充电口&#xff08;九孔&#xff09;。 引脚说明 上图给的是充电口的引脚图&#xff0c;充电枪的为镜像的。 慢充接口引脚说明 快充接口引脚说明 充电流程 慢充示意图 慢充&…...

AI智能分析网关V4将HTTP消息推送至安防监控视频汇聚EasyCVR平台的操作步骤

TSINGSEE青犀视频智能分析网关V4内置了近40种AI算法模型&#xff0c;支持对接入的视频图像进行人、车、物、行为等实时检测分析&#xff0c;上报识别结果&#xff0c;并能进行语音告警播放。硬件管理平台支持RTSP、GB28181协议、以及厂家私有协议接入&#xff0c;可兼容市面上常…...

程序代码篇---STM32串口通信

文章目录 前言1. 头文件和全局变量2. 串口1初始化函数3. 串口1发送字节函数4. 串口1发送字符串函数5. 串口1发送数字函数6. 重定义fputc函数7. 串口数据解析函数8. 串口2中断服务程序总结 前言 本次将介绍一个基于STM32微控制器的串口通信实现&#xff0c;包含了串口的初始化、…...

PECL(Positive Emitter-Coupled Logic)电平详解

一、PECL电平的定义与核心特性 PECL&#xff08;正射极耦合逻辑&#xff09;是一种基于 射极耦合逻辑&#xff08;ECL&#xff09;技术 的高速差分信号标准&#xff0c;采用 正电源供电&#xff08;如5V或3.3V&#xff09;。其核心特性包括 高速传输、低噪声、强抗干扰能力&am…...

1、操作系统引论

一、操作系统 会使用linux系统 建议大家先学会linux的基础指令&#xff0c;可以看菜鸟教程网站进行学习。 1、各种定义 操作系统定义 管理计算机的 硬件 和软件资源&#xff0c; 能对各类作业进行调度&#xff0c;方便用户使用计算机的程序集合。操作系统运行在内核态&#xf…...

L1-7 统一命名规范(java)

你所在的公司刚刚招收了几位程序员&#xff0c;然而这些程序员之前在不同的公司工作&#xff0c;所以他们习惯的变量命名规范可能存在差异&#xff0c;需要让他们都习惯公司要求的命名规范&#xff0c;然而这样可能会降低他们的工作效率。 你的上司找到了你&#xff0c;希望你…...

LVS + Keepalived 高可用集群

一、LVSKeepalived 原理 1.1.LVS 负载均衡原理 LVS&#xff08;Linux Virtual Server&#xff09;是一种基于 Linux 内核的负载均衡技术&#xff0c;它通过 IPVS&#xff08;IP Virtual Server&#xff09;模块来实现。LVS 可以将客户端的请求分发到多个后端服务器上&#xf…...

使用MySQL的Binlog来同步数据到ES当中

一、技术选型与核心原理 核心组件 • MySQL Binlog&#xff1a;ROW模式记录数据变更事件&#xff08;INSERT/UPDATE/DELETE&#xff09;&#xff0c;提供原子性变更流 • Canal/OpenReplicator&#xff1a;伪装MySQL Slave订阅Binlog&#xff08;本文以Canal 1.1.6为例&#xf…...

沐数科技数据开发岗笔试题2025

描述性统计 标准差 答案: A 解析: 标准差 衡量数据集中数值变化或离散程度的一种度量。它反映了数据集中的各个数值与数据集的平均值&#xff08;均值&#xff09;之间的偏离程度。标准差越大&#xff0c;表明数据的分布越分散&#xff1b;标准差越小&#xff0c;表明数据…...

什么是 HTML?

HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言: HyperText Markup LanguageHTML 不是一种编程语言&#xff0c;而是一种标记语言标记语言是一套标记标签 (markup tag)HTML 使用标记标签来描述网页HTML 文档包含了HTML 标签及文本内容HTML文档也叫做 web 页面 HT…...

coding ability 展开第四幕(滑动指针——巩固篇)超详细!!!!

文章目录 前言水果成篮思路 找到字符串中所有字母异位词思路 串联所有单词的子串思路 最小覆盖子串思路 总结 前言 本专栏上一篇博客&#xff0c;带着大家从认识滑动窗口到慢慢熟悉 相信大家对滑动窗口已经有了大概的认识 其实主要就是抓住——一段连续的区间 今天来学习一些滑…...

【Linux我做主】基础命令完全指南上篇

Linux基础命令完全指南【上篇】 Linux基础命令完全指南github地址前言命令行操作的引入Linux文件系统树形结构的根文件系统绝对路径和相对路径适用场景Linux目录下的隐藏文件 基本指令目录和文件相关1. ls2. cd和pwdcdpwd 3. touch4. mkdir5. cp6. mv移动目录时覆盖写入的两种特…...

101.在 Vue 3 + OpenLayers 使用 declutter 避免文字标签重叠

1. 前言 在使用 OpenLayers 进行地图开发时&#xff0c;我们经常需要在地图上添加点、线、区域等图形&#xff0c;并给它们附加文字标签。但当地图上的标注较多时&#xff0c;文字标签可能会发生重叠&#xff0c;导致用户无法清晰地查看地图信息。 幸运的是&#xff0c;OpenL…...

面试vue2开发时怎么加载编译速度(webpack)

可以输入命令获取默认 webpack 设置 vue inspect > set.js 1.使用缓存 configureWebpack: {cache: {type: filesystem, // 使用文件系统缓存类型buildDependencies: {config: [__filename] // 缓存依赖&#xff0c;例如webpack配置文件路径}}}, 2.启用 vue-loader (测试明…...

大模型推理后JSON数据后处理

大模型推理后JSON数据后处理 flyfish LLM 通常指的是 Large Language Model&#xff0c;也就是大语言模型&#xff0c;针对 JSON格式的输出&#xff0c;可以在大模型推理前、推理中、推理后进行处理&#xff0c;这里是在推理后进行处理。 针对模型输出结果&#xff0c;可采用结…...

面试总结:2024前端面试题

前几天写了一篇对面试官的吐槽&#xff0c;今天来总结一下最近面试的一些题目。题目不分具体公司了&#xff0c;毕竟题目的重复率不会特别高&#xff0c;就多做准备吧。 技术面还是离不开“八股文”&#xff0c;个人不喜欢也没办法&#xff0c;硬着头皮上&#xff0c;下面分几个…...

剑指 Offer II 083. 没有重复元素集合的全排列

comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20083.%20%E6%B2%A1%E6%9C%89%E9%87%8D%E5%A4%8D%E5%85%83%E7%B4%A0%E9%9B%86%E5%90%88%E7%9A%84%E5%85%A8%E6%8E%92%E5%88%97/README.md 剑指 Offer II 083. 没…...

SFT数据处理部分的思考

SFT数据及处理的业内共识 1&#xff0e;prompt的质量和多样性远重要于数据量级&#xff0c;微调一个 30 b 量级的base model只需要 10 w 量级的数据即可 参考&#xff1a;《LIMA&#xff1a;Less Is More for Alignment》 2&#xff0e;合成数据很重要&#xff01;一般需要通过…...

c++三级(枚举问题)

菲波那契数列(2) 题目描述 菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1&#xff0c;接下来每个数都等于前面2个数之和。 给出一个正整数a&#xff0c;要求菲波那契数列中第a个数对1000取模的结果是多少。 输入格式 第1行是测试数据的组数n&#xff0c;后面跟着n行…...

vb编程有哪些相关的IDE开发工具vb.net,Basic语言?

在编程领域&#xff0c;VB 系列拥有丰富多样的 IDE 开发工具&#xff0c;为不同需求的开发者提供了广泛的选择&#xff0c;以下为你详细介绍&#xff1a; 兼容 VB6 源码的开发工具 twinbasic&#xff1a;属于 VB7 系列&#xff0c;它几乎能 100% 兼容 VB6 源码&#xff0c;这…...

XSS跨站脚本攻击

1、什么是XSS攻击 XSS全称&#xff08;Cross Site Scripting&#xff09;跨站脚本攻击&#xff0c;为了避免与css层叠样式表名称冲突&#xff0c;所以改为xss&#xff0c;是最常见的web应用程序安全漏洞之一。它指的是恶意攻击者往web页面里插入恶意html代码&#xff08;JavaS…...

Uniapp 开发 App 端上架用户隐私协议实现指南

文章目录 引言一、为什么需要用户隐私协议&#xff1f;二、Uniapp 中实现用户隐私协议的步骤2.1 编写隐私协议内容2.2 在 Uniapp 中集成隐私协议2.3 DCloud数据采集说明2.4 配置方式3.1 Apple App Store3.2 Google Play Store 四、常见问题与解决方案4.1 隐私协议内容不完整4.2…...