设计模式 行为型 访问者模式(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)是一种行为设计模式,它允许你在不改变元素类的前提下定义作用于这些元素的新操作。这种模式将算法与对象结构分离,使得可以独立地变化那些保存在复杂对象结构中的元素的操作。 假设我们有一个复杂的对…...

golang之数据库操作
1.导入必要的包 import("database/sql"_ "github.com/go-sql-driver/mysql" //使用此作为数据库驱动 ) 2.相关操作 连接数据库 使用sql.Open()函数进行数据库的连接 db, err : sql.Open("mysql", "user:passwordtcp(127.0.0.1:3306)/db…...

对话新晋 Apache SeaTunnel Committer:张圣航的开源之路与技术洞察
近日,张圣航被推选为 Apache SeaTunnel 的 Committer成员。带着对技术的热情和社区的责任,他将如何跟随 Apache SeaTunnel 社区迈向新的高度?让我们一起来聆听他的故事。 自我介绍 请您简单介绍一下自己,包括职业背景、当前的工作…...

Mac 删除ABC 输入法
参考链接:百度安全验证 Mac下删除系统自带输入法ABC,正解!_mac删除abc输入法-CSDN博客 ABC 输入法和搜狗输入法等 英文有冲突~~ 切换后还会在英文状态,可以删除 ;可能会对DNS 输入有影响,但是可以通过复…...

《机器学习》之K-means聚类
目录 一、简介 二、K-means聚类实现步骤 1、初始化数据点、确定K值 2、通过距离分配数据点 3、更新簇中心 4、 迭代更新 三、聚类效果评价方式 1、轮廓系数的定义 2、整体轮廓系数 3、使用场景 4、优点 5、缺点 6、代码实现方法 四、K-means聚类代码实现 1、API接…...

日常工作之 Elasticsearch 常用查询语句汇总
日常工作之 Elasticsearch 常用查询语句汇总 查询现有索引创建索引查询索引结构插入数据查询索引数据查看索引磁盘占用信息删除索引查看分词器分词结果指定查询数量指定条件查询数据迁移统计索引数据量更新数据 在使用 es 的过程中,总是会用到 es 的查询语句&#x…...

WeakAuras NES Script(lua)
WeakAuras NES Script 修星脚本字符串 脚本1:NES !WA:2!TMZFWXX1zDxVAs4siiRKiBN4eV(sTRKZ5Z6opYbhQQSoPtsxr(K8ENSJtS50(J3D7wV3UBF7E6hgmKOXdjKsgAvZFaPTtte0mD60XdCmmecDMKruyykDcplAZiGPfWtSsag6myGuOuq89EVDV9wPvKeGBM7U99EFVVVV33VFFB8Z2TJ8azYMlZj7Ur3QDR(…...
JVM 触发类加载的条件有哪些?
目录 一、类加载生命周期 二、主动引用 2.1、创建类的实例 2.2、访问类的静态字段或静态方法 2.3、反射 2.4、初始化类的子类时,先初始化父类 2.5、虚拟机启动时,初始化 main 方法所在的类 2.6、动态语言支持 三、被动引用 3.1、通过子类引用父…...
Android实战经验篇-增加系统分区
系列文章转如下链接: Android Display Graphics系列文章-汇总 Android实战经验篇-系列文章汇总 本文主要包括部分: 一、Android分区说明 1.1 系统分区查看 1.2 分区表修改 1.3 验证新分区 二、源码修改 2.1 generate_extra_images 2.2 fstab 2…...
深入学习 Python 量化编程
深入学习 Python 量化编程 第一章:Python 基础与量化编程环境搭建 1.1 安装必要的库 首先,你需要安装一些在量化编程中常用的 Python 库。可以通过以下命令安装这些库: pip install numpy pandas matplotlib yfinance backtrader scikit-…...

机器学习笔记——特征工程
大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本笔记介绍机器学习中常见的特征工程方法、正则化方法和简要介绍强化学习。 文章目录 特征工程(Fzeature Engineering)1. 特征提取ÿ…...

4种革新性AI Agent工作流设计模式全解析
文章目录 导读:AI Agent的四种关键设计模式如下:1. 反思2. 工具使用3. 规划4. 多Agent协作 总结内容简介: 导读: AI Agent是指能够在特定环境中自主执行任务的人工智能系统,不仅接收任务,还自主制定和执行…...
【入门级】计算机网络学习
网络安全:前端开发者必知:Web安全威胁——XSS与CSRF攻击及其防范-CSDN博客 三次握手四次挥手:前端网络—三次握手四次挥手_前端三次握手-CSDN博客 http协议和https协议的区别:前端网络—http协议和https协议的区别-CSDN博客 网…...
安装 Jenkins 后无法访问用户名或密码且忘记这些凭证怎么办?
Jenkins 是一款功能强大的自动化服务器,在持续集成与交付(CI/CD)领域应用广泛。不过,用户在使用过程中,尤其是首次接触该系统或系统重启后,常常会遇到登录方面的问题。要是 Jenkins 突然要求输入用户名和密…...

day08_Kafka
文章目录 day08_Kafka课程笔记一、今日课程内容一、消息队列(了解)**为什么消息队列就像是“数据的快递员”?****实际意义**1、产生背景2、消息队列介绍2.1 常见的消息队列产品2.2 应用场景2.3 消息队列中两种消息模型 二、Kafka的基本介绍1、…...

安装conda 环境
conda create -n my_unet5 python3.8 (必须设置3.8版本) conda activate my_unet5...

【dockerros2】ROS2节点通信:docker容器之间/docker容器与宿主机之间
🌀 一个中大型ROS项目常需要各个人员分别完成特定的功能,而后再组合部署,而各人员完成的功能常常依赖于一定的环境,而我们很难确保这些环境之间不会相互冲突,特别是涉及深度学习环境时。这就给团队项目的部署落地带来了…...
使用外网访问在群晖中搭建思源docker
还是要折腾,之前发现用公网IP可以访问就没有折腾,今天ip变了,用不了了,一搜,发现有方法可以用域名访问,哎,太好了! 原文:分享我在 群晖 docker 部署 思源笔记 步骤 - 链…...

深度学习中的EMA技术:原理、实现与实验分析
深度学习中的EMA技术:原理、实现与实验分析 1. 引言 指数移动平均(Exponential Moving Average, EMA)是深度学习中一种重要的模型参数平滑技术。本文将通过理论分析和实验结果,深入探讨EMA的实现和效果。 深度学习中的EMA技术:原理、实现与…...

win32汇编环境,窗口程序中对按钮控件常用操作的示例
;运行效果 ;win32汇编环境,窗口程序中对按钮控件常用操作的示例 ;常用的操作,例如创建按钮控件,使其无效,改变文本,得到文本等。 ;将代码复制进radasm软件里,直接就可以编译运行。重点部分加备注。 ;>&g…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建
【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...

[KCTF]CORE CrackMe v2.0
这个Reverse比较古老,已经有20多年了,但难度确实不小。 先查壳 upx压缩壳,0.72,废弃版本,工具无法解压。 反正不用IDA进行调试,直接x32dbg中,dump内存,保存后拖入IDA。 这里说一下…...
Spring Boot SQL数据库功能详解
Spring Boot自动配置与数据源管理 数据源自动配置机制 当在Spring Boot项目中添加数据库驱动依赖(如org.postgresql:postgresql)后,应用启动时自动配置系统会尝试创建DataSource实现。开发者只需提供基础连接信息: 数据库URL格…...