设计模式 行为型 访问者模式(Visitor Pattern)与 常见技术框架应用 解析
访问者模式(Visitor Pattern)是一种行为设计模式,它允许你在不改变元素类的前提下定义作用于这些元素的新操作。这种模式将算法与对象结构分离,使得可以独立地变化那些保存在复杂对象结构中的元素的操作。
假设我们有一个复杂的对象结构,例如一个包含多种图形(圆形、矩形、三角形)的绘图系统。我们可能需要对这些图形进行多种操作,如计算面积、绘制轮廓、计算周长等。如果将这些操作的代码都放在图形类中,会使图形类变得非常臃肿。访问者模式就像是一个外来的“访问者”,它可以独立于图形类定义这些操作,然后在需要的时候“访问”图形并执行相应的操作。
一、核心思想
核心思想是将算法从对象的结构中分离出来,封装在独立的访问者对象中。这样一来,就可以在不修改对象结构的情况下,为该结构中的元素添加新的操作或行为。
二、定义与结构
- 定义:表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
- 结构:
- 访问者(Visitor):抽象类或者接口,定义了对每个具体元素访问的操作方法。
- 具体访问者(ConcreteVisitor):实现访问者接口,实现对具体元素的操作。
- 元素(Element):抽象类或者接口,定义了一个接受访问者的方法(
accept
方法)。 - 具体元素(ConcreteElement):实现元素接口,在
accept
方法中调用访问者对应的操作方法。 - 对象结构(ObjectStructure):包含可以被访问的元素集合,提供方法让访问者访问它的元素。
三、角色
- 访问者(Visitor):
- 这是一个抽象角色,用于声明访问具体元素的方法。例如,在图形系统中,它可能有
visitCircle
、visitRectangle
等方法,这些方法的参数通常是对应的具体元素。它定义了对不同类型元素进行操作的统一接口。
- 这是一个抽象角色,用于声明访问具体元素的方法。例如,在图形系统中,它可能有
- 具体访问者(ConcreteVisitor):
- 实现了访问者接口。它为每个访问方法提供了具体的实现,这些实现包含了针对具体元素的实际操作逻辑。比如,一个计算图形面积的具体访问者,会在
visitCircle
方法中实现计算圆形面积的逻辑,在visitRectangle
方法中实现计算矩形面积的逻辑等。
- 实现了访问者接口。它为每个访问方法提供了具体的实现,这些实现包含了针对具体元素的实际操作逻辑。比如,一个计算图形面积的具体访问者,会在
- 元素(Element):
- 抽象元素角色,通常是一个抽象类或接口,定义了
accept
方法。这个方法接受一个访问者对象作为参数,用于将当前元素自身传递给访问者,以便访问者执行相应的操作。
- 抽象元素角色,通常是一个抽象类或接口,定义了
- 具体元素(ConcreteElement):
- 实现了抽象元素角色定义的接口或抽象类。在
accept
方法中,它会调用访问者的相应方法,并将自身作为参数传递进去。例如,圆形类(Circle
)作为具体元素,在其accept
方法中会调用访问者的visitCircle
方法,并把自己(圆形对象)传递给访问者。
- 实现了抽象元素角色定义的接口或抽象类。在
- 对象结构(ObjectStructure):
- 这个角色用于管理和存储元素对象。它提供了方法来遍历元素集合,让访问者能够访问其中的每个元素。比如,在绘图系统中,对象结构可能是一个包含所有图形的列表,它有一个方法可以遍历这个列表,然后让访问者访问每个图形。
四、实现步骤及代码示例
- 步骤一:定义访问者接口和具体访问者类
// 访问者接口
interface Visitor {void visitCircle(Circle circle);void visitRectangle(Rectangle rectangle);
}
// 具体访问者类(计算面积)
class AreaCalculatorVisitor implements Visitor {@Overridepublic void visitCircle(Circle circle) {double area = Math.PI * circle.getRadius() * circle.getRadius();System.out.println("圆形面积:" + area);}@Overridepublic void visitRectangle(Rectangle rectangle) {double area = rectangle.getWidth() * rectangle.getHeight();System.out.println("矩形面积:" + area);}
}
- 步骤二:定义元素接口和具体元素类
// 元素接口
interface Shape {void accept(Visitor visitor);
}
// 具体元素类(圆形)
class Circle implements Shape {private double radius;public Circle(double radius) {this.radius = radius;}public double getRadius() {return radius;}@Overridepublic void accept(Visitor visitor) {visitor.visitCircle(this);}
}
// 具体元素类(矩形)
class Rectangle implements Shape {private double width;private double height;public Rectangle(double width, double height) {this.width = width;this.height = height;}public double getWidth() {return width;}public double getHeight() {return height;}@Overridepublic void accept(Visitor visitor) {visitor.visitRectangle(this);}
}
- 步骤三:定义对象结构类并使用访问者模式
import java.util.ArrayList;
import java.util.List;
// 对象结构类
class ShapeList {private List<Shape> shapes = new ArrayList<>();public void addShape(Shape shape) {shapes.add(shape);}public void accept(Visitor visitor) {for (Shape shape : shapes) {shape.accept(visitor);}}
}
// 主程序测试
public class Main {public static void main(String[] args) {ShapeList shapeList = new ShapeList();shapeList.addShape(new Circle(3.0));shapeList.addShape(new Rectangle(4.0, 5.0));Visitor areaCalculator = new AreaCalculatorVisitor();shapeList.accept(areaCalculator);}
}
- 在上述代码中,
Visitor
是访问者接口,AreaCalculatorVisitor
是具体访问者,用于计算图形面积。Shape
是元素接口,Circle
和Rectangle
是具体元素。ShapeList
是对象结构,用于管理图形对象。在main
方法中,我们创建了图形对象列表,添加了圆形和矩形对象,然后创建了面积计算访问者,并让对象结构接受访问者来计算每个图形的面积。
五、常见技术框架应用
1、编译器中的语法树遍历
- 在编译器开发中,语法树是一个复杂的对象结构。访问者模式可以用于遍历语法树并执行语义分析或代码生成等操作。
- 步骤一:定义语法树节点(元素)接口和具体节点类
// 语法树节点接口
interface ASTNode {void accept(ASTVisitor visitor);
}
// 具体节点类(表达式节点)
class ExpressionNode implements ASTNode {// 表达式内容等属性@Overridepublic void accept(ASTVisitor visitor) {visitor.visitExpressionNode(this);}
}
// 具体节点类(语句节点)
class StatementNode implements ASTNode {// 语句内容等属性@Overridepublic void accept(ASTVisitor visitor) {visitor.visitStatementNode(this);}
}
- 步骤二:定义访问者接口和具体访问者类(语义分析访问者)
// 访问者接口
interface ASTVisitor {void visitExpressionNode(ExpressionNode node);void visitStatementNode(StatementNode node);
}
// 具体访问者类(语义分析)
class SemanticAnalysisVisitor implements ASTVisitor {@Overridepublic void visitExpressionNode(ExpressionNode node) {// 进行表达式语义分析,如检查操作数类型等}@Overridepublic void visitStatementNode(StatementNode node) {// 进行语句语义分析,如检查变量声明等}
}
- 步骤三:定义语法树(对象结构)类并使用访问者模式进行遍历
import java.util.ArrayList;
import java.util.List;
// 语法树类
class SyntaxTree {private List<ASTNode> nodes = new ArrayList<>();public void addNode(ASTNode node) {nodes.add(node);}public void accept(ASTVisitor visitor) {for (ASTNode node : nodes) {node.accept(visitor);}}
}
// 主程序测试(假设在编译器的某个阶段)
public class Compiler {public static void main(String[] args) {SyntaxTree syntaxTree = new SyntaxTree();ASTNode expressionNode = new ExpressionNode();ASTNode statementNode = new StatementNode();syntaxTree.addNode(expressionNode);syntaxTree.addNode(statementNode);ASTVisitor semanticAnalysisVisitor = new SemanticAnalysisVisitor();syntaxTree.accept(semanticAnalysisVisitor);}
}
- 这里的语法树由各种语法节点组成,通过访问者模式,语义分析访问者可以遍历语法树并对每个节点进行语义分析,而不需要将语义分析代码嵌入到语法树节点的内部。
2、前端框架中的访问者模式示例
以下是一些前端框架中访问者模式应用的具体例子:
处理复杂UI组件树
假设我们有一个复杂的用户界面,它由各种不同的UI组件构成,比如按钮、输入框、下拉菜单等。每个组件可能都需要执行特定的操作,例如验证、序列化或渲染。我们可以定义一个Visitor
来封装这些操作,而不是将所有逻辑都放在组件内部,这样可以使代码更加模块化和易于维护。
// 抽象访问者 (Abstract Visitor)
class UIComponentVisitor {visitButton(button) { }visitInput(input) { }visitDropdown(dropdown) { }
}// 具体访问者 (Concrete Visitors)
class ValidatorVisitor extends UIComponentVisitor {visitButton(button) {// 验证按钮的逻辑console.log('Validating button:', button);}visitInput(input) {if (!input.value) {console.error('Input is required:', input);} else {console.log('Input validated:', input);}}visitDropdown(dropdown) {// 验证下拉菜单的逻辑console.log('Validating dropdown:', dropdown);}
}class SerializerVisitor extends UIComponentVisitor {visitButton(button) {// 序列化按钮的状态console.log('Serializing button:', button);}visitInput(input) {// 序列化输入框的值console.log('Serializing input value:', input.value);}visitDropdown(dropdown) {// 序列化下拉菜单的选择console.log('Serializing dropdown selection:', dropdown.selectedOptions);}
}// 抽象元素 (Abstract Element)
class UIComponent {constructor() {this.name = 'UIComponent';}accept(visitor) {visitor[`visit${this.constructor.name}`](this);}
}// 具体元素 (Concrete Elements)
class Button extends UIComponent {constructor(text) {super();this.text = text;this.name = 'Button';}
}class Input extends UIComponent {constructor(value) {super();this.value = value;this.name = 'Input';}
}class Dropdown extends UIComponent {constructor(options, selectedOptions) {super();this.options = options;this.selectedOptions = selectedOptions;this.name = 'Dropdown';}
}// 使用访问者模式
const components = [new Button('Submit'), new Input('Some text'), new Dropdown(['Option1', 'Option2'], ['Option1'])];const validator = new ValidatorVisitor();
const serializer = new SerializerVisitor();components.forEach(component => component.accept(validator));
console.log('\n');
components.forEach(component => component.accept(serializer));
在这个例子中,ValidatorVisitor
和SerializerVisitor
是具体的访问者,它们实现了针对不同类型UI组件的不同行为。UIComponent
及其子类作为具体元素,提供了accept
方法以接受访问者的访问。这种方式使得我们可以很容易地添加新的操作类型,而无需修改现有的UI组件类。
React 中的虚拟 DOM 遍历与更新(间接体现访问者模式思想)
- 背景:
在 React 中,虚拟 DOM(Virtual DOM)是一个关键概念。它是真实 DOM 结构在 JavaScript 对象层面的一种表示,通过对比虚拟 DOM 的前后状态变化来决定如何高效地更新真实 DOM。 - 分析:
- 元素(类似访问者模式中的元素角色):React 组件对应的虚拟 DOM 节点可以看作是元素。例如,一个简单的
<div>
组件在虚拟 DOM 里会被表示成一个包含各种属性(如props
、children
等)的 JavaScript 对象,它定义了accept
(这里没有显式的accept
方法名,但有类似机制)操作,也就是允许 React 的更新机制来处理它。 - 访问者(类似访问者模式中的访问者角色):React 的
Diffing
算法(用于对比新旧虚拟 DOM 差异的机制)以及后续的Reconciliation
过程(协调更新的过程)可以看作是访问者。Diffing
算法会遍历虚拟 DOM 树(从根节点开始),访问每个虚拟 DOM 节点(元素),去判断节点的类型、属性以及子节点等是否发生了变化,这个过程就类似访问者对不同元素进行访问并执行相应操作。例如,当检测到一个<div>
组件的props
发生了改变,访问者(更新机制)就会执行对应的更新真实 DOM 中该<div>
对应部分的操作,比如更新style
属性或者innerHTML
等。 - 具体过程示例:
假如有一个简单的 React 组件结构如下:
- 元素(类似访问者模式中的元素角色):React 组件对应的虚拟 DOM 节点可以看作是元素。例如,一个简单的
function App() {return (<div className="app"><h1>Hello</h1><p>World</p></div>);
}
当组件的状态发生改变(比如 className
变为 app-new
),React 会重新构建新的虚拟 DOM 树,然后通过 Diffing
算法这个“访问者”去遍历新旧虚拟 DOM 树的各个节点(元素),对比发现 <div>
节点的 className
属性变化了,就会执行相应的更新真实 DOM 中对应 <div>
元素的操作,将 class
属性更新为 app-new
。
Vue.js 的模板编译与指令解析(体现访问者模式思路)
- 背景:
Vue.js 在将模板(template
)编译成渲染函数(render
函数)以及解析模板中的指令(如v-if
、v-for
等)时运用了类似访问者模式的思路。 - 分析:
- 元素(类似访问者模式中的元素角色):模板中的 HTML 标签以及文本节点等可以看作是元素。例如
<div v-if="show">{{ message }}</div>
中的<div>
标签、文本插值{{ message }}
等,它们构成了整个模板这个“数据结构”,并且每个元素都能被访问处理。 - 访问者(类似访问者模式中的访问者角色):Vue 的模板编译器就是访问者。它会对模板这个元素集合进行遍历,解析每个元素。比如,对于指令类的元素,像遇到
v-if
指令时,访问者(编译器)会解析出条件判断逻辑,根据对应的数据(show
变量的值)来决定是否生成该<div>
元素的渲染代码;对于文本插值元素{{ message }}
,访问者会解析出需要将对应的数据(message
值)渲染到此处的操作。 - 具体过程示例:
假设我们有如下 Vue 模板:
- 元素(类似访问者模式中的元素角色):模板中的 HTML 标签以及文本节点等可以看作是元素。例如
<template><div><p v-if="isShow">This is visible</p><p v-else>This is hidden</p><span>{{ greeting }}</span></div>
</template>
当 Vue 进行模板编译时,编译器这个“访问者”会遍历整个模板的各个元素。对于带有 v-if
指令的 <p>
元素,它会检查 isShow
数据的值,如果为 true
,则生成将 This is visible
渲染到页面的相关代码逻辑;对于文本插值的 <span>
元素,编译器会根据 greeting
变量的值,生成将其正确渲染到对应位置的代码,从而实现模板到渲染函数的转换,后续基于渲染函数就能更新页面 DOM 了。
Ember.js 的渲染系统(部分体现访问者模式)
- 背景:
Ember.js 有一套自己的渲染机制,用于根据定义的模板和组件来生成和更新页面内容。 - 分析:
- 元素(类似访问者模式中的元素角色):在 Ember.js 中,组件对应的模板内容、DOM 元素等可以视为元素。例如,一个自定义的组件模板里包含的各种 HTML 标签、绑定的数据等组成了要处理的元素集合。
- 访问者(类似访问者模式中的访问者角色):Ember.js 的渲染引擎和相关的更新机制充当访问者。渲染引擎会遍历组件的模板元素,比如遇到绑定数据的地方(类似
{{someProperty}}
),访问者(渲染引擎)会去获取对应的数据值,并将其正确渲染到 DOM 中;当组件状态变化触发更新时,更新机制同样会访问各个元素,判断哪些元素需要重新渲染,然后执行相应的更新操作。 - 具体过程示例:
假设有一个 Ember.js 组件的模板如下:
{{! my-component.hbs }}
<h2>{{title}}</h2>
<p>Description: {{description}}</p>
当 Ember.js 渲染这个组件时,渲染引擎这个“访问者”会访问模板中的每个元素,对于 {{title}}
和 {{description}}
这些绑定数据的元素,会从组件对应的 JavaScript 对象(包含 title
和 description
等属性)中获取相应的值,然后将其渲染到对应的 HTML 标签内,生成最终的 DOM 结构展示给用户。当组件的 title
或 description
属性值发生变化时,更新机制又会作为访问者再次访问这些元素,重新获取新值并更新 DOM 展示。
总之,在前端框架中,访问者模式(或其类似思路)常被用于高效地处理页面元素的渲染、更新以及对模板、DOM 相关结构的操作,使得代码结构更清晰,便于扩展和维护不同的功能逻辑。
六、应用场景
数据结构稳定,但作用于数据结构的操作经常变化的场景。
需要将数据结构与数据操作分离的场景。
需要对不同数据类型进行操作,而不适用分支判断具体类型的场景。
元素具体类型并非单一,访问者均可操作的场景。
- 数据结构的操作分离:当有一个复杂的数据结构(如树形结构、图形系统中的图形集合等),并且需要对这个数据结构执行多种不同的操作(如计算、打印、转换等)时,访问者模式可以将操作代码从数据结构类中分离出来,使得数据结构的定义更加清晰,操作的扩展更加容易。
- 编译器设计:如前面提到的语法树遍历,用于语义分析、中间代码生成、代码优化等阶段。不同的编译器阶段可以定义不同的访问者来对语法树进行操作。
- XML文档处理:可以将XML文档看作是一个树形的数据结构,访问者模式可以用于对XML元素进行不同的操作,如验证、转换、提取信息等。
- 编译器构建:在编译器中,不同的节点类型(如表达式、语句等)可以通过访问者模式进行不同的处理,如语法检查、代码生成等。
- 文档处理:在文档处理系统中,不同的文档元素(如文本、图片、表格等)可以通过访问者模式进行不同的处理,如渲染、统计字数等。
- 图形界面工具:在图形界面工具中,不同的UI组件(如按钮、文本框、菜单等)可以通过访问者模式进行不同的操作,如绘制、事件处理等。
- 数据分析:在数据分析系统中,不同的数据结构(如树、图、表等)可以通过访问者模式进行不同的分析操作,如计算总和、平均值等。
- 游戏开发:在游戏开发中,不同的游戏对象(如玩家、敌人、道具等)可以通过访问者模式进行不同的操作,如更新状态、渲染图像等。
七、优缺点
优点:
- 分离操作和数据结构:使得数据结构的定义和操作的定义可以独立变化,提高了代码的可维护性和可扩展性。当需要添加新的操作时,只需要创建新的访问者类,而不需要修改数据结构类。
- 符合开闭原则:对于数据结构和操作的扩展是开放的,对于修改是封闭的。可以方便地添加新的元素(数据结构中的节点)和新的访问者(操作)。
- 增加代码的复用性:访问者类可以在多个不同的数据结构上复用,只要这些数据结构的元素接口是兼容的。
缺点:
- 增加了代码的复杂性:访问者模式需要定义多个接口和类,包括访问者接口、具体访问者类、元素接口、具体元素类和对象结构类等,这使得代码结构相对复杂,对于简单的应用场景可能会增加不必要的复杂性。
- 违背了迪米特法则:因为访问者模式需要访问数据结构中的元素,可能会导致访问者和元素之间的耦合度过高,访问者需要知道元素的内部结构和接口细节,这在一定程度上违背了迪米特法则(最少知识原则)。
相关文章:
设计模式 行为型 访问者模式(Visitor Pattern)与 常见技术框架应用 解析
访问者模式(Visitor Pattern)是一种行为设计模式,它允许你在不改变元素类的前提下定义作用于这些元素的新操作。这种模式将算法与对象结构分离,使得可以独立地变化那些保存在复杂对象结构中的元素的操作。 假设我们有一个复杂的对…...
stable diffusion 量化学习笔记
文章目录 一、一些tensorRT背景及使用介绍1)深度学习介绍2)TensorRT优化策略介绍3)TensorRT基础使用流程4)dynamic shape 模式5)TensorRT模型转换 二、TensorRT转onnx模型1)onnx介绍2)背景知识&…...
金融项目实战 04|JMeter实现自动化脚本接口测试及持续集成
目录 一、⾃动化测试理论 二、自动化脚本 1、添加断言 1️⃣注册、登录 2️⃣认证、充值、开户、投资 2、可重复执行:清除测试数据脚本按指定顺序执行 1️⃣如何可以做到可重复执⾏? 2️⃣清除测试数据:连接数据库setup线程组 ①明确…...
无需昂贵GPU:本地部署开源AI项目LocalAI在消费级硬件上运行大模型
无需昂贵GPU:本地部署开源AI项目LocalAI在消费级硬件上运行大模型 随着人工智能技术的快速发展,越来越多的AI模型被广泛应用于各个领域。然而,运行这些模型通常需要高性能的硬件支持,特别是GPU(图形处理器)…...
selenium学习笔记
一.搭建环境 1.安装chrome #下载chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb#安装chrome apt --fix-broken install ./google-chrome-stable_current_amd64.deb2.安装chromedriver 首先先查看版本:google-chrome --…...
SOME/IP协议详解 基础解读 涵盖SOME/IP协议解析 SOME/IP通讯机制 协议特点 错误处理机制
车载以太网协议栈总共可划分为五层,分别为物理层,数据链路层,网络层,传输层,应用层,其中今天所要介绍的内容SOME/IP就是一种应用层协议。 SOME/IP协议内容按照AUTOSAR中的描述,我们可以更进一步…...
nginx 实现 正向代理、反向代理 、SSL(证书配置)、负载均衡 、虚拟域名 ,使用其他中间件监控
我们可以详细地配置 Nginx 来实现正向代理、反向代理、SSL、负载均衡和虚拟域名。同时,我会介绍如何使用一些中间件来监控 Nginx 的状态和性能。 1. 安装 Nginx 如果你还没有安装 Nginx,可以通过以下命令进行安装(以 Ubuntu 为例࿰…...
基于单片机的智能花卉浇水系统的设计与实现
摘要: 随着人们生活水平的不断提高,生活节奏也越来越快。人们经常忽视办公室或者家居的花卉,忘记浇水。本文设计了一种基于单片机的智能浇水系统。目的是解决养殖花卉的人忘记浇水的问题。本系统以单片机AT89S52为控制芯片,能够按…...
《使用 YOLOV8 和 KerasCV 进行高效目标检测》
《使用 YOLOV8 和 KerasCV 进行高效目标检测》 作者:Gitesh Chawda创建日期:2023/06/26最后修改时间:2023/06/26描述:使用 KerasCV 训练自定义 YOLOV8 对象检测模型。 (i) 此示例使用 Keras 2 在 Colab 中…...
【Domain Generalization(3)】领域泛化与文生图之 -- QUOTA 任意领域中的生成物体的数量可控
系列文章目录 【Domain Generalization(1)】增量学习/在线学习/持续学习/迁移学习/多任务学习/元学习/领域适应/领域泛化概念理解第一篇了解了 DG 的概念,那么接下来将介绍 DG 近年在文生图中的相关应用/代表性工作。【Domain Generalization(2)】领域泛化在文生图…...
qml XmlListModel详解
1、概述 XmlListModel是QtQuick用于从XML数据创建只读模型的组件。它可以作为各种view元素的数据源,比如ListView、GridView、PathView等;也可以作为其他和model交互的元素的数据源。通过XmlRole定义角色,如name、age和height,并…...
CAPL如何设置TCP/IP传输层动态端口范围
在TCP/IP协议中,应用程序通过传输层协议TCP/UDP传输数据,接收方传输层收到数据后,根据传输层端口号把接收的数据上交给正确的应用程序。我们可以简单地认为传输层端口号是应用程序的标识,这就是为什么我们说应用程序在使用TCP/IP协议通信时要打开传输层端口号或者绑定端口号…...
Pandas常用数据类型
扩展库pandas常用的数据结构如下: (1)Series:带标签的一维数组 (2)DatetimeIndes:时间序列 (3)DateFrame:带标签且大小可变的二维表格结构 (4…...
【AI大模型】BERT GPT ELMo模型的对比
目录 🍔 BERT, GPT, ELMo之间的不同点 🍔 BERT, GPT, ELMo各自的优点和缺点 🍔 小结 学习目标 理解BERT, GPT, ELMo相互间的不同点理解BERT, GPT, ELMo相互比较下的各自优点和缺点 🍔 BERT, GPT, ELMo之间的不同点 关于特征提取…...
探索AGI:智能助手与自我赋能的新时代
目录 1 AGI1.1 DeepMind Levels(2023年11月)1.2 OpenAI Levels(2024年7月)1.3 对比与总结1.4 AGI可能诞生哪里 2 基于AI的智能自动化助手2.1 通用型大模型2.2 专业的Agent和模型工具开发框架2.3 编程与代码生成助手2.4 视频和多模态生成2.5 商…...
Oracle Dataguard(主库为双节点集群)配置详解(5):将主库复制到备库并启动同步
Oracle Dataguard(主库为双节点集群)配置详解(5):将主库复制到备库并启动同步 目录 Oracle Dataguard(主库为双节点集群)配置详解(5):将主库复制到备库并启动…...
webrtc自适应分辨率的设置
DegradationPreference 是一个枚举类,用于在视频编码或实时通信(如 WebRTC)中指定系统资源不足时如何处理质量下降的策略。以下是该枚举类的中文解释: enum class DegradationPreference {// 禁用:不根据资源过载信号…...
提供的 IP 地址 10.0.0.5 和子网掩码位 /26 来计算相关的网络信息
网络和IP地址计算器 https://www.sojson.com/convert/subnetmask.html提供的 IP 地址 10.0.0.5 和子网掩码位 /26 来计算相关的网络信息。 子网掩码转换 子网掩码 /26 的含义二进制表示:/26 表示前 26 位是网络部分,剩下的 6 位是主机部分。对应的子网掩码为 255…...
WPF系列八:图形控件Path
简介 Path控件支持一种称为路径迷你语言(Path Mini-Language)的紧凑字符串格式,用于描述复杂的几何图形。这种语言通过一系列命令字母和坐标来定义路径上的点和线段,最终绘制出想要的图形。 绘制任意形状:可以用来绘…...
如何移除git中被跟踪的commit文件
忽略已被跟踪的文件 问题描述 如果某个文件已经被 Git 跟踪(即已被提交到仓库),即使后来将其添加到 .gitignore 文件中,Git 仍会继续跟踪它。 解决方案 更新 .gitignore 文件 将需要忽略的文件加入 .gitignore: .env…...
15. C语言 函数指针与回调函数
本章目录: 前言什么是函数指针?定义声明方式 函数指针的基本用法示例:最大值函数输出示例: 回调函数与函数指针什么是回调函数?通俗解释 示例:回调函数实现动态数组填充输出示例: 进一步探索:带…...
tomcat12启动流程源码分析
信息: Server.服务器版本: Apache Tomcat/12.0.x-dev 信息: Java虚拟机版本: 21下载源码https://github.com/apache/tomcat,并用idea打开,配置ant编译插件,或者使用我的代码 启动脚本是/bin/startup.bat,内部又执行了bin\cata…...
Pycharm 使用教程
一、基本配置 1. 切换Python解释器 pycharm切换解释器版本 2. pycharm虚拟环境配置 虚拟环境的目的:创建适用于该项目的环境,与系统环境隔离,防止污染系统环境(包括需要的库)虚拟环境配置存放在项目根目录下的 ven…...
数据仓库: 9- 数据仓库数据治理
目录 9- 数据治理9.1 数据标准化9.1.1 数据标准化的定义9.1.2 数据标准化的重要性9.1.3 数据标准化的主要内容9.1.4 数据标准化的实施步骤9.1.5 数据标准化常用工具9.1.6 数据标准化的挑战与应对策略9.1.7 案例分析9.1.8 总结 9.2 主数据管理(MDM)9.2.1 主数据管理的核心目标9.…...
Kutools for Excel 简体中文版 - 官方正版授权
Kutools for Excel 是一款超棒的 Excel 插件,就像给你的 Excel 加了个超能助手。它有 300 多种实用功能,现在还有 AI 帮忙,能把复杂的任务变简单,重复的事儿也能自动搞定,不管是新手还是老手都能用得顺手。有了它&…...
回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测
回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测 目录 回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB实MLR多元线性回归多输入单输出回归预测。 程序设计 完整代码:回…...
lerna使用指南
lerna版本 以下所有配置命令都是基于v8.1.9,lerna v5 v7版本差别较大,在使用时,注意自身的lerna版本。 lerna开启缓存及缓存配置 nx缓存是v5版本以后才有的,小于该版本的无法使用该功能。 初始化配置 缓存配置文件nx.json&am…...
LightGCN:为推荐系统简化图卷积网络的创新之作
LightGCN: Simplifying and Powering Graph Convolution Network for RecommendationSIGIR2020Collaborative Filtering, Recommendation, Embedding Propagation, Graph Neural Network 🌟 研究背景 在信息爆炸的互联网时代,个性化推荐系统成为缓解信…...
【图像去噪】论文精读:High-Quality Self-Supervised Deep Image Denoising(HQ-SSL)
请先看【专栏介绍文章】:【图像去噪(Image Denoising)】关于【图像去噪】专栏的相关说明,包含适配人群、专栏简介、专栏亮点、阅读方法、定价理由、品质承诺、关于更新、去噪概述、文章目录、资料汇总、问题汇总(更新中) 文章目录 前言Abstract1 Introduction2 Convoluti…...
Elasticsarch:使用全文搜索在 ES|QL 中进行过滤 - 8.17
8.17 在 ES|QL 中引入了 match 和 qstr 函数,可用于执行全文过滤。本文介绍了它们的作用、使用方法、与现有文本过滤方法的区别、当前的限制以及未来的改进。 ES|QL 现在包含全文函数,可用于使用文本查询过滤数据。我们将回顾可用的文本过滤方法…...
17.C语言输入输出函数详解:从缓存原理到常用函数用法
目录 1.前言2.缓存和字节流3.printf4.scanf5.sscanf6.getchar与putchar7.puts与gets 1.前言 本篇原文为:C语言输入输出函数详解:从缓存原理到常用函数用法。 更多C进阶、rust、python、逆向等等教程,可点击此链接查看:酷程网 C…...
高等数学学习笔记 ☞ 不定积分与积分公式
1. 不定积分的定义 1. 原函数与导函数的定义: 若函数可导,且,则称函数是函数的一个原函数,函数是函数的导函数。 备注: ①:若函数是连续的,则函数一定存在原函数,反之不对。 ②&…...
Debye-Einstein-模型拟合比热容Python脚本
固体比热模型中的德拜模型和爱因斯坦模型是固体物理学中用于估算固体热容的两种重要原子振动模型。 爱因斯坦模型基于三种假设:1.晶格中的每一个原子都是三维量子谐振子;2.原子不互相作用;3.所有的原子都以相同的频率振动(与德拜…...
Ubuntu24.04安装AppImage报错AppImages require FUSE to run.
报错如下: 解决: sudo apt install libfuse2t64如果不行: sudo add-apt-repository universe sudo apt install libfuse2t64安装时又报错: [10354:0109/100149.571068:FATAL:setuid_sandbox_host.cc(158)] The SUID sandbox hel…...
3_CSS3 渐变 --[CSS3 进阶之路]
CSS3 引入了渐变(gradients),它允许在两个或多个指定的颜色之间显示平滑的过渡。CSS3 支持两种类型的渐变: 线性渐变(Linear Gradients):颜色沿着一条线性路径变化,可以是水平、垂直…...
uniapp 左右滑动切换Tab
各种开发会遇到很多奇葩的需求,今天这个是在页面 左右滑动,然后自动去切换Tab <viewtouchstart"touchStart"touchcancel"touchCancel"touchend"touchEnd"><components is"xxx"/></view>//---…...
STM32 FreeRTOS 任务创建和删除实验(动态方法)
动态创建,堆栈是在FreeRTOS管理的堆内存里,注意任务不要重复创建。 xxxxx_STACK_SIZE 128 uxTaskGetStackHighWaterMark()获取指定任务的任务栈的历史剩余最小值,根据这个结果适当调整启动任务的大小。 实验目标 学会 xTaskCreate( ) 和 vTaskDelete( ) 的使用: start_…...
宝塔面板 申请证书后 仍然提示不安全
证书显示有效,但是网站显示不安全 导致的原因是引入静态文件使用的是HTTP,查看方法为F12打开console控制台 可以看到静态文件全部都是HTTP 网站采用wordpress搭建,基于问题解决,其他方式搭建也是一样,处理掉所有的H…...
透明部署、旁路逻辑串联的区别
背景 需讨论防火墙到底是串联,还是旁挂。 通常串联指的就是“透明部署”,旁挂指的就是“逻辑串联”。 透明部署(串联) 也称为透明模式或桥接模式,是一种安全设备的部署方式。在这种模式下,安全设备被串联…...
C++实现设计模式---原型模式 (Prototype)
原型模式 (Prototype) 原型模式 是一种创建型设计模式,它通过复制现有对象来创建新对象,而不是通过实例化。 意图 使用原型实例指定要创建的对象类型,并通过复制该原型来生成新对象。提供一种高效创建对象的方式,尤其是当对象的…...
Canvas简历编辑器-选中绘制与拖拽多选交互方案
Canvas简历编辑器-选中绘制与拖拽多选交互方案 在之前我们聊了聊如何基于Canvas与基本事件组合实现了轻量级DOM,并且在此基础上实现了如何进行管理事件以及多层级渲染的能力设计。那么此时我们就依然在轻量级DOM的基础上,关注于实现选中绘制与拖拽多选交…...
kotlin的dagger hilt依赖注入
依赖注入(dependency injection, di)是设计模式的一种,它的实际作用是给对象赋予实例变量。 基础认识 class MainActivity : ComponentActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceSta…...
Flink类加载机制详解
1. 总览 在运行Flink应用时,它会加载各种类,另外我们用户代码也会引入依赖,由于他们依赖版本以及加载顺序等不同,就可能会导致冲突,所以很要必要了解Flink是如何加载类的。 根据加载的来源的不同,我们可以将类分为三种: Java Classpath:Java类路径下,这是Java通用的…...
在VSCode中设置bash命令行内容简写
在VSCode中设置bash命令行内容简写 1、打开shell配置文件2、在配置文件的末尾,添加以下行来创建别名3、重新加载配置文件以使更改生效4、在命令行使用缩写执行命令 比如,在VSCode的bash中输入 gc daily,而实际执行 git checkout daily. 1、…...
特制一个自己的UI库,只用CSS、图标、emoji图 第二版
图: 代码: index.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>M…...
51_Lua面向对象编程
面向对象编程(Object Oriented Programming,OOP)是一种非常流行的计算机编程架构。像C++、Java、Objective-C、Smalltalk、C#、Ruby等编程语言都支持面向对象编程。 1.面向对象编程特性 面向对象编程是一种编程范式,它使用“对象”来设计软件。对象是数据和行为的封装单元…...
Kafka——两种集群搭建详解 k8s
1、简介 Kafka是一个能够支持高并发以及流式消息处理的消息中间件,并且Kafka天生就是支持集群的,今天就主要来介绍一下如何搭建Kafka集群。 Kafka目前支持使用Zookeeper模式搭建集群以及KRaft模式(即无Zookeeper)模式这两种模式搭…...
OPT: Open Pre-trained Transformer语言模型
摘要 大规模语言模型通常需要数十万计算日的训练时间,展现了在零样本和小样本学习中的显著能力。鉴于其计算成本之高,这些模型在没有大量资本投入的情况下难以复现。对于那些通过API提供的少数模型,研究者无法获取完整的模型权重,…...
开源模型应用落地-LangChain高阶-记忆组件-RedisChatMessageHistory正确使用(八)
一、前言 LangChain 的记忆组件发挥着至关重要的作用,其旨在协助大语言模型(LLM)有效地留存历史对话信息。通过这一功能,使得大语言模型在对话过程中能够更出色地维持上下文的连贯性和一致性,进而能够像人类的记忆运作方式那样,进行更为自然、流畅且智能化的交互。 它仿佛…...
http和https有哪些不同
http和https有哪些不同 1.数据传输的安全性:http非加密,https加密 2.端口号:http默认80端口,https默认443端口 3.性能:http基于tcp三次握手建立连接,https在tcp三次握手后还有TLS协议的四次握手确认加密…...