【架构美学】Java 访问者模式:解构数据与操作的双重分发哲学
一、模式定义与核心思想
访问者模式(Visitor Pattern)是一种行为型设计模式,其核心目标是将数据操作与数据结构分离。通过定义一个独立的访问者类,使得新增对数据结构中元素的操作时,无需修改元素本身的类结构,只需添加新的访问者即可。这种模式遵循 "开闭原则",特别适用于数据结构相对稳定,但操作算法频繁变化的场景。
从设计本质来看,访问者模式实现了双重分发(Double Dispatch):首先根据元素类型确定调用哪个访问者的方法,然后根据访问者类型确定具体的操作逻辑。这种机制使得操作集合可以独立于元素结构进行扩展,形成 "数据结构不变,操作可变" 的灵活架构。
核心角色解析
访问者模式包含五个关键角色:
- 抽象元素(Element):定义接受访问者的接口
accept(Visitor visitor)
- 具体元素(ConcreteElement):实现接受访问者的方法,调用访问者的具体操作
- 抽象访问者(Visitor):声明针对所有具体元素的访问方法(如
visitConcreteElementA()
) - 具体访问者(ConcreteVisitor):实现抽象访问者定义的具体操作逻辑
- 对象结构(Object Structure):管理元素集合,提供遍历元素的方法
其核心思想可以概括为:将数据结构的 "被动接受操作" 转变为访问者的 "主动发起访问",通过双重分发机制解耦数据与操作。
二、适用场景与问题引入
2.1 典型应用场景
当系统满足以下条件时,访问者模式是理想选择:
- 数据结构稳定(元素类型很少变化),但操作算法频繁新增或修改
- 需要对不同类型的元素执行不同操作,且操作逻辑可能跨元素类型
- 需要将相关操作集中到一个访问者类中,避免在元素类中散落业务逻辑
- 需要对元素进行批处理操作,且操作过程需要访问元素的内部状态
2.2 传统实现的困境
假设我们需要统计不同类型员工(普通员工、经理)的工资和奖金,传统实现会在元素类中直接添加操作方法:
java
// 传统实现:元素类耦合操作逻辑
class Employee {protected String name;protected double salary;public abstract double calculateTotal(); // 不同员工计算方式不同
}class CommonEmployee extends Employee {private double bonus;@Overridepublic double calculateTotal() {return salary + bonus;}
}class Manager extends Employee {private double stockOption;@Overridepublic double calculateTotal() {return salary + stockOption;}
}
当需要新增 "计算纳税额"" 生成考勤报告 " 等操作时,每个元素类都需要修改,违背开闭原则,且操作逻辑分散在多个元素类中,难以维护。
2.3 访问者模式解决方案
通过分离操作逻辑到访问者类,元素类仅保留数据结构:
- 元素类实现
accept(Visitor)
方法,接收访问者 - 访问者类定义针对不同元素的操作方法(如
visitCommonEmployee()
) - 对象结构遍历元素,调用每个元素的
accept()
方法触发访问者操作
这种设计使得新增操作(如计算纳税)只需添加新的访问者,无需修改员工类。
三、模式实现的关键步骤
3.1 定义抽象元素接口
java
// 抽象元素:员工
public abstract class Employee {protected String name;protected double baseSalary;public abstract void accept(Visitor visitor); // 接受访问者// 省略getter/setter
}// 具体元素:普通员工
public class CommonEmployee extends Employee {private double bonus; // 奖金@Overridepublic void accept(Visitor visitor) {visitor.visit(this); // 调用访问者的具体访问方法}// 省略getter/setter
}// 具体元素:经理
public class Manager extends Employee {private double stockOption; // 股票期权@Overridepublic void accept(Visitor visitor) {visitor.visit(this);}// 省略getter/setter
}
3.2 定义抽象访问者与具体实现
java
// 抽象访问者:定义所有元素的访问方法
public interface Visitor {void visit(CommonEmployee employee); // 访问普通员工void visit(Manager employee); // 访问经理
}// 具体访问者:工资计算访问者
public class SalaryVisitor implements Visitor {@Overridepublic void visit(CommonEmployee employee) {double total = employee.getBaseSalary() + employee.getBonus();System.out.println("普通员工" + employee.getName() + " 总收入:" + total);}@Overridepublic void visit(Manager employee) {double total = employee.getBaseSalary() + employee.getStockOption();System.out.println("经理" + employee.getName() + " 总收入:" + total);}
}
3.3 对象结构管理元素集合
java
// 对象结构:员工列表
public class EmployeeList {private List<Employee> employees = new ArrayList<>();public void addEmployee(Employee employee) {employees.add(employee);}public void accept(Visitor visitor) {for (Employee employee : employees) {employee.accept(visitor); // 遍历调用每个元素的accept方法}}
}
3.4 客户端调用
java
public class Client {public static void main(String[] args) {// 创建对象结构EmployeeList list = new EmployeeList();list.addEmployee(new CommonEmployee("张三", 8000, 5000));list.addEmployee(new Manager("李四", 20000, 100000));// 创建访问者并执行操作Visitor salaryVisitor = new SalaryVisitor();list.accept(salaryVisitor); // 输出所有员工的工资计算结果}
}
四、UML 类图与运行机制
4.1 标准类图结构
plantuml
@startuml
interface Visitor {+visitCommonEmployee(CommonEmployee)+visitManager(Manager)
}
interface Employee {+accept(Visitor): void
}
class CommonEmployee {-name: String-baseSalary: double-bonus: double+accept(Visitor)+getName(): String+getBaseSalary(): double+getBonus(): double
}
class Manager {-name: String-baseSalary: double-stockOption: double+accept(Visitor)+getName(): String+getBaseSalary(): double+getStockOption(): double
}
class SalaryVisitor {+visitCommonEmployee(CommonEmployee)+visitManager(Manager)
}
class EmployeeList {-employees: List<Employee>+addEmployee(Employee)+accept(Visitor)
}
Visitor <|.. SalaryVisitor
Employee <|.. CommonEmployee
Employee <|.. Manager
EmployeeList "1" -- "*" Employee : contains
CommonEmployee --> "1" Employee: implements
Manager --> "1" Employee: implements
@enduml
4.2 双重分发机制解析
- 第一次分发:调用元素的
accept(visitor)
方法,根据元素类型(CommonEmployee/Manager)决定调用哪个重载的accept
方法 - 第二次分发:在元素的
accept
方法中调用visitor.visit(this)
,根据访问者类型(SalaryVisitor/OtherVisitor)和元素的实际类型,确定执行哪个具体的访问方法
这种机制使得操作逻辑完全由访问者决定,元素类只负责数据存储。
五、优缺点深度剖析
5.1 核心优势
- 分离数据与操作:数据结构专注于存储,操作逻辑集中在访问者,符合单一职责原则
- 强大的扩展性:新增操作只需添加新的访问者,无需修改现有元素和对象结构
- 集中相关操作:将跨元素的操作(如统计、报表生成)集中到一个访问者,避免逻辑散落
- 支持复杂操作:访问者可以在遍历元素时维护上下文状态(如累计统计数据),适合批处理
5.2 局限性与适用边界
- 数据结构变更困难:如果元素类需要新增属性或方法,所有访问者都需要修改,违背开闭原则(因此要求数据结构稳定)
- 增加系统复杂度:双重分发机制和访问者与元素的双向依赖,可能让代码难以理解
- 违反依赖倒置原则:具体元素类(如 CommonEmployee)暴露给访问者,导致高层模块依赖具体类
- 不适用于小系统:简单场景下使用访问者模式可能显得笨重,直接在元素类中实现操作更高效
5.3 适用判断清单
使用前请确认:
- 数据结构是否基本稳定(未来很少新增元素类型)?
- 操作是否频繁新增或修改?
- 是否需要对不同元素执行差异化操作?
- 操作逻辑是否需要跨元素类型组合(如统计所有元素的某种属性总和)?
六、与相关模式的对比分析
6.1 vs 双重分发(Double Dispatch)
- 访问者模式是双重分发的典型实现,通过
accept()
和visit()
方法组合实现两次类型判断 - 双重分发是一种设计机制,访问者模式是其具体应用场景
6.2 vs 责任链模式
- 访问者模式:数据结构中的元素被动接受访问者的操作,操作逻辑集中在访问者
- 责任链模式:请求沿着处理链传递,每个处理者决定是否处理请求
- 核心区别:前者是数据驱动的操作分发,后者是请求驱动的处理链
6.3 vs 策略模式
- 访问者模式:处理多元素类型的不同操作,操作之间可能关联元素状态
- 策略模式:处理同一类型对象的不同算法策略,算法之间相互独立
- 适用场景:前者适用于多维度(元素类型 + 操作类型)变化,后者适用于单一维度(算法)变化
6.4 vs 解释器模式
- 两者都处理复杂结构的操作,但:
- 访问者模式关注对现有结构的操作扩展
- 解释器模式关注构建自定义语言的解析规则
七、JDK 与开源框架中的应用
7.1 Java IO 中的文件访问
Java NIO.2 的FileVisitor
接口是典型的访问者模式实现:
java
// 抽象访问者
public interface FileVisitor<T> {FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs);FileVisitResult visitFile(T file, BasicFileAttributes attrs);// 其他方法...
}// 具体访问者实现(如统计文件大小)
public class SizeVisitor implements FileVisitor<Path> {private long totalSize = 0;@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {totalSize += attrs.size();return FileVisitResult.CONTINUE;}// 省略其他方法
}
7.2 编译器的语义分析
在编译器设计中,抽象语法树(AST)作为对象结构,语义分析器作为访问者:
- 每个 AST 节点(元素)实现
accept(Visitor)
方法 - 语义分析器(访问者)遍历节点,执行类型检查、作用域分析等操作
7.3 Spring Expression Language (SpEL)
SpEL 的表达式解析器使用访问者模式处理不同表达式节点(如变量节点、方法调用节点),每个节点接受解析器访问者,生成对应的求值逻辑。
八、最佳实践与设计原则
8.1 元素类的设计要点
- 元素类应尽量稳定,避免频繁修改接口(新增方法会导致所有访问者修改)
accept()
方法应声明为 final 或设计为模板方法,防止子类覆盖破坏访问机制- 对于内部状态,提供必要的访问方法(getter)供访问者使用,避免暴露实现细节
8.2 访问者类的组织策略
- 按操作类型组织访问者(如
SalaryVisitor
、TaxVisitor
),保持单一职责 - 复杂场景可使用访问者适配器(Visitor Adapter)提供空实现,减少具体访问者的方法实现
java
// 访问者适配器(默认实现所有方法)
public abstract class AbstractVisitor implements Visitor {@Override public void visitCommonEmployee(CommonEmployee e) {}@Override public void visitManager(Manager e) {}
}// 具体访问者只需覆盖需要的方法
public class TaxVisitor extends AbstractVisitor {@Override public void visitCommonEmployee(CommonEmployee e) { /* 实现逻辑 */ }
}
8.3 对象结构的遍历控制
- 对象结构应提供统一的遍历接口(如
accept(Visitor)
),隐藏内部数据结构(列表、树、图等) - 对于复杂结构(如组合模式中的树结构),对象结构需递归调用子元素的
accept()
方法
8.4 类型安全的双重分发
通过在抽象访问者中为每个具体元素定义独立的访问方法(如visitCommonEmployee()
),确保编译期类型安全,避免运行时类型转换。
九、典型案例:员工数据统计系统
假设我们需要实现一个员工管理系统,支持以下功能:
- 计算不同岗位员工的总薪酬
- 生成员工考勤报表
- 统计管理层占比
使用访问者模式设计:
- 元素类:
Employee
(抽象)、CommonEmployee
、Manager
- 访问者类:
SalaryCalculator
、AttendanceReporter
、ManagementAnalyzer
- 对象结构:
Department
(管理员工列表)
当新增 "计算员工纳税额" 功能时,只需添加TaxCalculatorVisitor
,无需修改任何员工类,体现了模式的扩展性优势。
十、总结与设计哲学
访问者模式是 "数据与操作分离" 设计思想的极致体现,它教会我们:
- 当数据结构稳定但操作多变时,通过引入独立的访问者层解耦变化维度
- 利用双重分发机制实现类型安全的动态调度
- 在系统设计中区分 "本质稳定" 与 "频繁变化" 的部分,让稳定部分成为扩展的基石
然而,其适用边界也提醒我们:当数据结构可能频繁变更时(如新增元素类型),访问者模式会带来维护成本,此时应优先考虑其他模式(如策略模式或直接在元素类中实现操作)。
对于 Java 开发者,掌握访问者模式不仅能理解 JDK 和框架中的设计(如 NIO 的文件访问),更能在处理复杂业务逻辑(如报表生成、语义分析)时,构建出可扩展的优雅架构。记住:好的设计不是追求模式的堆砌,而是在合适的场景选择合适的工具。当你的系统需要 "让数据结构保持稳定,同时自由扩展操作" 时,访问者模式就是那个正确的选择。
相关文章:
【架构美学】Java 访问者模式:解构数据与操作的双重分发哲学
一、模式定义与核心思想 访问者模式(Visitor Pattern)是一种行为型设计模式,其核心目标是将数据操作与数据结构分离。通过定义一个独立的访问者类,使得新增对数据结构中元素的操作时,无需修改元素本身的类结构&#x…...
UE5无法编译问题解决
1. vs编译 2. 删除三个文件夹 参考...
Java可变参数与Collections工具类详解
Java可变参数与Collections工具类详解 一、可变参数(Variable Arguments) 1.1 基本概念 可变参数是Java 5引入的特性,允许在方法中定义数量可变的形参。其核心特点是:形参个数可以动态变化(0个、1个、多个ÿ…...
Git版本管理命令reset
目录 命令 git reset 场景一只回退 工作区代码 场景二回退暂存库与工作区 场景三回退暂存库,工作区,版本库内容 命令 git reset git reset --[soft/mixed(默认)/hard] [文件] soft:只回退版本库中内容 mixed:回退暂存区&…...
改进模糊C均值时序聚类+编码器状态识别!IPOA-FCM-Transformer组合模型
改进模糊C均值时序聚类编码器状态识别!IPOA-FCM-Transformer组合模型 目录 改进模糊C均值时序聚类编码器状态识别!IPOA-FCM-Transformer组合模型效果分析基本描述程序设计参考资料 效果分析 基本描述 1.创新未发表!研究亮点!时序…...
Zookeeper入门(三)
Zookeeper Java 客户端 项目构建 ookeeper 官方的客户端没有和服务端代码分离,他们为同一个jar 文件,所以我们直接引入 zookeeper的maven即可, 这里版本请保持与服务端版本一致,不然会有很多兼容性的问题 1 <dependency>…...
使用Redission来实现布隆过滤器
简述布隆过滤器 布隆过滤器是一种概率型数据结构,它可以用来判断一个元素是否在一个集合中。我们当时使用的是Redisson实现的布隆过滤器。它的底层原理是,先初始化一个比较大的数组,里面存放的是二进制0或1。一开始都是0,当一个k…...
Seata源码—6.Seata AT模式的数据源代理一
大纲 1.Seata的Resource资源接口源码 2.Seata数据源连接池代理的实现源码 3.Client向Server发起注册RM的源码 4.Client向Server注册RM时的交互源码 5.数据源连接代理与SQL句柄代理的初始化源码 6.Seata基于SQL句柄代理执行SQL的源码 7.执行SQL语句前取消自动提交事务的源…...
Spring-Beans的生命周期的介绍
目录 1、Spring核心组件 2、Bean组件 2.1、Bean的定义 2.2、Bean的生命周期 1、实例化 2、属性填充 3、初始化 4、销毁 2.3、Bean的执行时间 2.4、Bean的作用域 3、常见问题解决方案 4、与Java对象区别 前言 关于bean的生命周期,如下所示: …...
目标检测新突破:用MSBlock打造更强YOLOv8
文章目录 YOLOv8的现状与挑战YOLO-MS的MSBlock简介MSBlock的工作原理MSBlock的优势 利用MSBlock改进YOLOv8替换YOLOv8主干网络中的部分模块代码实现:替换CSP模块为MSBlock 在YOLOv8的颈部(Neck)中插入MSBlock代码实现:在颈部区域插…...
[SpringBoot]Spring MVC(4.0)
获取Header 传统获取 header 从 HttpServletRequest 中获取 RequestMapping("/r8")public String r8(HttpServletRequest request) {String userAgent request.getHeader("User-Agent");return "userAgent: "userAgent;}使用浏览器访问后&…...
Linux概述:从内核到开源生态
Linux概述:从内核到开源生态 Linux 是当今计算机领域最核心的开源操作系统内核,其影响力已渗透到服务器、嵌入式设备、云计算甚至超级计算机等各个领域。本章将深入解析Linux的本质、核心架构及其背后的开源哲学。 1. Linux的本质:不只是“操…...
【ubuntu24.04】pycharm 死机结束进程
windows 远程pycharm到ubuntu执行程序 pycharm 在调试过程中,内存耗尽,然后死机了 pycharm 进程 (base) rootk8s-master-pfsrv:/home/zhangbin/下载# ps -ef | grep pycharm root 121245 3230568 0 5月14 pts/8 00:00:00 /bin/bash --rcfile …...
【PRB】深度解析GaN中最浅的受主缺陷
2025 年 1 月 16 日,Virginia Commonwealth University 的 M. A. Reshchikov 和 SUNY–Albany 的 B. McEwen 等人在《Physical Review B》期刊发表了题为《Identity of the shallowest acceptor in GaN》的文章,基于对 50 多个 Be 掺杂 GaN 样品的光致发光实验以及 Heyd-Scus…...
Flink CEP是什么?
Apache Flink 的 CEP(Complex Event Processing,复杂事件处理) 是 Flink 提供的一个库,用于在无界数据流中检测符合特定模式的事件组合。 🎯 一、什么是 CEP? ✅ 定义: CEP 是一种从连续的数据…...
基于STM32的多传感器融合的设施农业小型搬运机器人避障控制系统设计
一、系统总体设计目标 针对设施农业场景中狭窄通道、障碍物多样(如农机具、作物植株、水管)的特点,设计一款基于 STM32 的小型搬运机器人避障控制系统。系统通过多传感器融合实现 360 环境感知,采用模糊 PID 控制算法实现平滑避障,满足温室、大棚等场景的搬运需求。 二、…...
从零开始实现大语言模型(十六):加载开源大语言模型参数
1. 前言 预训练大语言模型的难点不在于算法,而在于数据和算力,绝大多数企业和机构都没有预训练大语言模型的算力资源。在工业界的大语言模型应用实践中,通常会使用领域数据微调开源大语言模型参数,以构建领域大语言模型。 本文介…...
Spark,数据提取和保存
以下是使用 Spark 进行数据提取(读取)和保存(写入)的常见场景及代码示例(基于 Scala/Java/Python,不含图片操作): 一、数据提取(读取) 1. 读取文件数据&a…...
java19
1.集合体系结构 注意: 2.collection遍历之迭代器遍历 一次循环只能一次next方法的原因: 原因:集合长度是单数就报错 3.collection遍历之增强for遍历 如何代码简写呢:集合名.for回车 4.collection遍历之Lambda表达式遍历 5.使用多态…...
从0到1吃透卷积神经网络(CNN):原理与实战全解析
一、开篇:CNN 在 AI 领域的地位 在当今人工智能(AI)飞速发展的时代,卷积神经网络(Convolutional Neural Network,简称 CNN)无疑是深度学习领域中最为耀眼的明星之一 。它就像是 AI 世界里的超级…...
建一个结合双向长短期记忆网络(BiLSTM)和条件随机场(CRF)的模型
构建一个结合双向长短期记忆网络(BiLSTM)和条件随机场(CRF)的模型,通常用于序列标注任务,如命名实体识别(NER)、词性标注(POS Tagging)等。下面我将通过口述的…...
mvc-ioc实现
IOC 1)耦合/依赖 依赖,是谁离不开谁 就比如上诉的Controller层必须依赖于Service层,Service层依赖于Dao 在软件系统中,层与层之间存在依赖。我们称之为耦合 我们系统架构或者设计的一个原则是ÿ…...
符合Python风格的对象(再谈向量类)
再谈向量类 为了说明用于生成对象表示形式的众多方法,我们将使用一个 Vector2d 类,它与第 1 章中的类似。这一节和接下来的几节会不断实 现这个类。我们期望 Vector2d 实例具有的基本行为如示例 9-1 所示。 示例 9-1 Vector2d 实例有多种表示形式 &g…...
4.1.8文件共享
知识总览 基于索引节点的共享方式(硬链接): 让不同用户的文件目录项指向同一个文件的索引节点 用户1创建文件1,并让文件目录项aaa指向了文件1,这个文件对应了一个索引节点,这个索引节点 包含了文件的物理地址和文件的其他属性信…...
[LevelDB]LevelDB版本管理的黑魔法-为什么能在不锁表的情况下管理数据?
文章摘要 LevelDB的日志管理系统是怎么通过双链表来进行数据管理为什么LevelDB能够在不锁表的情况下进行日志新增 适用人群: 对版本管理机制有开发诉求,并且希望参考LevelDB的版本开发机制。数据库相关从业者的专业人士。计算机狂热爱好者,对计算机的…...
普通用户的服务器连接与模型部署相关记录
普通用户的服务器连接与模型部署相关记录 一、从登录到使用自己的conda 1.账号登陆: ssh xxx172.31.226.236 2.下载与安装conda: 下载conda: wget -c https://repo.anaconda.com/archive/Anaconda3-2023.03-1-Linux-x86_64.sh 安装con…...
WebSocket解决方案的一些细节阐述
今天我们来看看WebSocket解决方案的一些细节问题: 实际上,集成WebSocket的方法都有相关的工程挑战,这可能会影响项目成本和交付期限。在最简单的层面上,构建 WebSocket 解决方案似乎是添加接收实时更新功能的前进方向。但是&…...
架构思维:构建高并发扣减服务_分布式无主架构
文章目录 Pre无主架构的任务简单实现分布式无主架构 设计和实现扣减中的返还什么是扣减的返还返还实现原则原则一:扣减完成才能返还原则二:一次扣减可以多次返还原则三:返还的总数量要小于等于原始扣减的数量原则四:返还要保证幂等…...
C++函数基础:定义与调用函数,参数传递(值传递、引用传递)详解
1. 引言 函数是C编程中的核心概念之一,它允许我们将代码模块化,提高代码的可读性、复用性和可维护性。本文将深入探讨: 函数的定义与调用参数传递方式(值传递 vs 引用传递)应用场景与最佳实践 2. 函数的定义与调用 …...
深入解析Python中的Vector2d类:从基础实现到特殊方法的应用
引言 在Python面向对象编程中,特殊方法(或称魔术方法)是实现对象丰富行为的关键。本文将以Vector2d类为例,详细讲解如何通过特殊方法为自定义类添加多种表示形式和操作能力。 Vector2d类的基本行为 Vector2d类是一个二维向量类…...
【25软考网工】第六章(7)网络安全防护系统
博客主页:christine-rr-CSDN博客 专栏主页:软考中级网络工程师笔记 大家好,我是christine-rr !目前《软考中级网络工程师》专栏已经更新三十多篇文章了,每篇笔记都包含详细的知识点,希望能帮助到你&#x…...
Mac下载bilibili视频
安装 安装 yt-dlp brew install yt-dlp安装FFmpeg 用于合并音视频流、转码等操作 brew install ffmpeg使用 下载单个视频 查看可用格式 yt-dlp -F --cookies-from-browser chrome "https://www.bilibili.com/video/BV15B4y1G7F3?spm_id_from333.788.recommend_more_vid…...
6个月Python学习计划:从入门到AI实战(前端开发者进阶指南)
作者:一名前端开发者的进阶日志 计划时长:6个月 每日学习时间:2小时 覆盖方向:Python基础、爬虫开发、数据分析、后端开发、人工智能、深度学习 📌 目录 学习目标总览每日时间分配建议第1月:Python基础与编…...
批量处理 Office 文档 高画质提取图片、视频、音频素材助手
各位办公小能手们!你们有没有遇到过想从 Office 文档里提取图片、音频和视频,却又搞得焦头烂额的情况?今天就给大家介绍一款超厉害的工具——OfficeImagesExtractor! 这货的核心功能那可真是杠杠的!首先是高画质提取&a…...
【甲方安全建设】Python 项目静态扫描工具 Bandit 安装使用详细教程
文章目录 一、工具简介二、工具特点1.聚焦安全漏洞检测2.灵活的扫描配置3.多场景适配4.轻量且社区活跃三、安装步骤四、使用方法场景1:扫描单个Python文件场景2:递归扫描整个项目目录五、结果解读六、总结一、工具简介 Bandit 是由Python官方推荐的静态代码分析工具(SAST)…...
【推荐】新准则下对照会计报表172个会计科目解释
序号 科目名称 对应的会计报表项目 序号 科目名称 对应的会计报表项目 一、资产类 二、负债类 1 1001 库存现金 货币资金 103 2001 短期借款 短期借款 2 1002 银行存款 货币资金 104 2101 交易性金融负债 易性金融负债 3 1012 其他货币资…...
IntelliJ IDEA设置编码集
在IntelliJ IDEA中设置Properties文件的编码格式,主要涉及以下步骤和注意事项: 1. 全局和项目编码设置 打开设置界面:File -> Settings -> Editor -> File Encodings。在Global Encoding和Project Encoding下拉菜单中均选择UT…...
类魔方 :多变组合,灵活复用
文章目录 一、类的基础1. 类的基本结构与语法1. 类的定义与实例化2. 成员变量(属性)3. 构造函数(Constructor)4. 成员方法 2. 访问修饰符1. 基本访问规则2. 子类对父类方法的重写3. 构造函数的访问修饰符4. 参数属性与继承总结 3.…...
支持多方式拼接图片的软件
软件介绍 本文介绍一款名为 PicMerger 的图片拼接软件。 拼接亮点 PicMerger 这款软件最大的亮点在于,它能够将不同分辨率的图片完美地拼接在一起。拼接时会自动以分辨率最小的图片为标准,操作十分方便。 拼接方式与设置 该软件支持横向和纵向的拼接…...
Qt音视频开发过程中一个疑难杂症的解决方法/ffmpeg中采集本地音频设备无法触发超时回调
一、前言 最近在做实时音视频通话的项目中,遇到一个神奇的问题,那就是用ffmpeg采集本地音频设备,当音频设备拔掉后,采集过程会卡死在av_read_frame函数中,尽管设置了超时时间,也设置了超时回调interrupt_c…...
Android studio Could not move temporary workspace
Android studio Could not move temporary workspace 在Window上运行AS出现Could not move temporary workspace报错方法一(有效)方法二方法三方法四总结 在Window上运行AS出现Could not move temporary workspace报错 Could not move temporary workspa…...
深度估计中为什么需要已知相机基线(known camera baseline)?
在计算机视觉和立体视觉的上下文中,“已知相机基线”(known camera baseline)的解释 1. 相机基线的定义 相机基线是指两个相机中心之间的距离。在立体视觉系统中,通常有两个相机(或一个相机在不同位置拍摄两张图像&a…...
Spring Cloud 技术实战
Spring Cloud 简介 Spring Cloud 是基于 Spring Boot 构建的微服务框架,提供了一套完整的微服务解决方案。它利用 Spring Boot 的开发便利性,并通过各种组件简化分布式系统的开发。 核心组件 Spring Cloud Netflix Eureka: 服务注册与发现Spring Clou…...
《云端共生体:Flutter与AR Cloud如何改写社交交互规则》
当Flutter遇上AR Cloud,一场关于社交应用跨设备增强现实内容共享与协作的变革正在悄然发生。 Flutter是谷歌推出的一款开源UI软件开发工具包,其最大的优势在于能够实现一套代码,多平台部署,涵盖iOS、Android、Web、Windows、macO…...
【数据结构】1-3 算法的时间复杂度
数据结构知识点合集:数据结构与算法 • 知识点 • 时间复杂度的定义 1、算法时间复杂度 事前预估算法时间开销T(n)与问题规模 n 的关系(T 表示 “time”) 2、语句频度 算法中语句的执行次数 对于以上算法,语句频度:…...
Science Robotics 封面论文:基于形态学开放式参数化的仿人灵巧手设计用于具身操作
人形机械手具有无与伦比的多功能性和精细运动技能,使其能够精确、有力和稳健地执行各种任务。在古生物学记录和动物王国中,我们看到了各种各样的替代手和驱动设计。了解形态学设计空间和由此产生的涌现行为不仅可以帮助我们理解灵巧的作用及其演变&#…...
Vue百日学习计划Day24-28天详细计划-Gemini版
总目标: 在 Day 24-27 熟练掌握 Vue.js 的各种模板语法,包括文本插值、属性绑定、条件渲染、列表渲染、事件处理和表单绑定,并能结合使用修饰符。 所需资源: Vue 3 官方文档 (模板语法): https://cn.vuejs.org/guide/essentials/template-syntax.htmlVu…...
C++_数据结构_哈希表(hash)实现
✨✨ 欢迎大家来到小伞的大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C学习 小伞的主页:xiaosan_blog 制作不易!点个赞吧!!谢谢喵!&…...
elasticsearch kibana ik 各版本下载
https://release.infinilabs.com/analysis-ik/stable/或者 https://github.com/infinilabs/analysis-ik/releases...
Uniapp 与 Uniapp X 对比:新手上手指南及迁移到 Uniapp X 的注意事项
文章目录 前言一、Uniapp 与 Uniapp X 核心区别二、Uniapp X 的核心优势三、新手学习 Uniapp X 必备技能栈3.1 基础技能要求3.2 平台相关知识3.3 工具链掌握 四、从 Uniapp 迁移到 Uniapp X 的注意事项4.1 语法转换:4.2 组件替换:4.3 状态管理࿱…...