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

《图解设计模式》笔记(六)访问数据结构

十三、Visitor 模式:访问数据结构并处理数据

Visitor:访问者

我们会“处理”在数据结构中保存着的元素,通常把“处理”代码放在表示数据结构的类中。

但每增加一种处理,就不得不去修改表示数据结构的类。

在 Visitor模式中,数据结构与处理被分离。编写一个表示“访问者”的类来访问数据结构中的元素,并把对各元素的处理交给访问者类。

这样,当需要增加新的处理时,我们只需要编写新的访问者,然后让数据结构可以接受访问者的访问即可。

示例中,使用Composite模式(第11章)中用到的那个文件和文件夹的例子作为访问者要访问的数据结构。访问者会访问由文件和文件夹构成的数据结构,然后显示出文件和文件夹的一览。

示例程序类图

在这里插入图片描述

Visitor

public abstract class Visitor {public abstract void visit(File file);public abstract void visit(Directory directory);
}

Element

public interface Element {public abstract void accept(Visitor v);
}

Entry

import java.util.Iterator;public abstract class Entry implements Element {public abstract String getName();                                   // 获取名字public abstract int getSize();                                      // 获取大小public Entry add(Entry entry) throws FileTreatmentException {       // 增加目录条目throw new FileTreatmentException();}public Iterator iterator() throws FileTreatmentException {    // 生成Iteratorthrow new FileTreatmentException();}public String toString() {                                          // 显示字符串return getName() + " (" + getSize() + ")";}
}

File

public class File extends Entry {private String name;private int size;public File(String name, int size) {this.name = name;this.size = size;}public String getName() {return name;}public int getSize() {return size;}public void accept(Visitor v) {v.visit(this);}
}

Directory

import java.util.Iterator;
import java.util.ArrayList;public class Directory extends Entry {private String name;                    // 文件夹名字private ArrayList dir = new ArrayList();      // 目录条目集合public Directory(String name) {         // 构造函数this.name = name;}public String getName() {               // 获取名字return name;}public int getSize() {                  // 获取大小int size = 0;Iterator it = dir.iterator();while (it.hasNext()) {Entry entry = (Entry)it.next();size += entry.getSize();}return size;}public Entry add(Entry entry) {         // 增加目录条目dir.add(entry);return this;}public Iterator iterator() {      // 生成Iteratorreturn dir.iterator();}public void accept(Visitor v) {         // 接受访问者的访问v.visit(this);}
}

ListVisitor

import java.util.Iterator;public class ListVisitor extends Visitor {private String currentdir = "";                         // 当前访问的文件夹的名字public void visit(File file) {                  // 在访问文件时被调用System.out.println(currentdir + "/" + file);}// 我们先显示当前文件夹的名字,接着调用iterator方法获取文件夹的Iterator,// 然后通过Iterator遍历文件夹中的所有目录条目并调用它们各自的accept方法。// 由于文件夹中可能存在着许多目录条目,逐一访问会非常困难。// accept方法调用visit方法,visit方法又会调用accept方法,这样就形成了非常复杂的递归调用。// 通常的递归调用是某个方法调用自身,在 Visitor模式中,则是accept方法与visit方法之间相互递归调用。public void visit(Directory directory) {   // 在访问文件夹时被调用System.out.println(currentdir + "/" + directory);String savedir = currentdir;currentdir = currentdir + "/" + directory.getName();Iterator it = directory.iterator();while (it.hasNext()) {Entry entry = (Entry)it.next();entry.accept(this);}currentdir = savedir;}
}

FileTreatmentException

public class FileTreatmentException extends RuntimeException {public FileTreatmentException() {}public FileTreatmentException(String msg) {super(msg);}
}

Main

public class Main {public static void main(String[] args) {try {System.out.println("Making root entries...");Directory rootdir = new Directory("root");Directory bindir = new Directory("bin");Directory tmpdir = new Directory("tmp");Directory usrdir = new Directory("usr");rootdir.add(bindir);rootdir.add(tmpdir);rootdir.add(usrdir);bindir.add(new File("vi", 10000));bindir.add(new File("latex", 20000));rootdir.accept(new ListVisitor());              System.out.println("");System.out.println("Making user entries...");Directory yuki = new Directory("yuki");Directory hanako = new Directory("hanako");Directory tomura = new Directory("tomura");usrdir.add(yuki);usrdir.add(hanako);usrdir.add(tomura);yuki.add(new File("diary.html", 100));yuki.add(new File("Composite.java", 200));hanako.add(new File("memo.tex", 300));tomura.add(new File("game.doc", 400));tomura.add(new File("junk.mail", 500));rootdir.accept(new ListVisitor());              } catch (FileTreatmentException e) {e.printStackTrace();}}
}

Visitor与 Element之间的相互调用

结合时序图学习示例程序的处理流程
当一个文件夹下有两个文件时,示例程序的处理流程:

在这里插入图片描述

① Main类生成ListVisitor的实例。示例中,Main类还生成了其他的Directory类和File类的实例,本图中省略。
② Main类调用Directory类的accept方法。这时传递的参数是ListVisitor的实例,本图中省略。
③ Directory类的实例调用接收到的参数ListVisitor的visit(Directory)方法。
④ ListVisitor类的实例会访问文件夹,并调用找到的第一个文件的accept方法。传递的参数是自身(this)。
⑤ File的实例调用接收到的参数ListVisitor的visit(File)方法。注意这时ListVisitor的visit(Directory)还在执行中(并非多线程执行,而是表示visit(Directory)还存在于调用堆栈(callstack)中的意思。在时序图中,表示生命周期的长方形的右侧发生了重叠就说明了这一点)。
⑥ 从visit(File)返回到accept,接着又从accept也返回出来,然后调用另外一个File的实例(同一文件夹下的第二个文件)的accept方法。传递的参数是ListVisitor的实例this。
⑦ 与前面一样,File的实例调用visit(File)方法。所有的处理完成后,逐步返回,最后回到Main类中的调用 accept方法的地方。

注意:

对于Directory类的实例和 File类的实例,调用了它们的accept方法
对于每一个Directory类的实例和File类的实例,其accept方法只被调用一次
对于Listvisitor 的实例,调用了它的visit(Directory)和visit(File)方法
处理visit(Directory)和visit(File)的是同一个ListVisitor的实例

在Visitor模式中,visit方法将“处理”都集中在ListVisitor里了

角色

在这里插入图片描述

  • Visitor(访问者)

    负责对数据结构中每个具体的元素(ConcreteElement角色)声明一个用于访问XXXXX的visit(XXXXX)方法。

    visit(XXXXX)是用于处理XXXXX的方法,负责实现该方法的是ConcreteVisitor角色。

    示例中是Visitor类。

  • ConcreteVisitor (具体的访问者)

    负责实现Visitor角色所定义的接口(API)。它要实现所有的visit(XXXXX)方法,即实现如何处理每个ConcreteElement角色。

    示例中是ListVisitor类。

    如同在ListVisitor中,currentdir字段的值不断发生变化一样,随着visit(XXXXX)处理的进行,ConcreteVisitor角色的内部状态也会不断地发生变化。

  • Element(元素)

    表示Visitor角色的访问对象。它声明了接受访问者的accept方法。

    accept方法接收到的参数是 Visitor角色。

    示例中是Element 接口。

  • ConcreteElement

    负责实现Element角色所定义的接口(API)。

    示例中是File类和Directory类。

  • ObjectStructure (对象结构)

    负责处理Element角色的集合。

    ConcreteVisitor角色为每个Element角色都准备了处理方法。

    示例中是Directory类(一人分饰两角)。

    为了让ConcreteVisitor角色可以遍历处理每个Element角色,示例中在Directory类中实现了iterator方法。

扩展思路的要点

双重分发

Visitor模式中方法的调用关系。
accept(接受)方法的调用方式:element.accept(visitor);
visit(访问)方法的调用方式:visitor.visit(element);
它们是相反的关系。element接受visitor,而visitor又访问element
ConcreteElement 和 ConcreteVisitor这两个角色共同决定了实际进行的处理。
这种消息分发的方式一般被称为双重分发(double dispatch)。

为什么要弄得这么复杂

Visitor模式的目的是将处理从数据结构中分离出来。数据结构很重要,它能将元素集合和关联在一起。
但是注意,保存数据结构与以数据结构为基础进行处理是两种不同的东西。
示例中,创建了ListVisitor类作为显示文件夹内容的ConcreteVisitor角色。
还可以编写进行其他处理的ConcreteVisitor角色,该角色可以独立于File类和 Directory类,即,Visitor模式提高了File类和Directory类作为组件的独立性。
如果将进行处理的方法定义在File类和Directory类中,当每次要扩展功能,增加新的“处理”时,就只能修改File类和Directory类。

开闭原则——对扩展开放,对修改关闭

关于功能扩展和修改,有个开闭原则(The Open-Closed Principle, OCP)。
对扩展(extension)是开放(open)的
对修改(modification)是关闭(close)的

易增加 ConcreteVisitor角色

使用Visitor模式可以很容易地增加ConcreteVisitor角色。因为具体的处理被交给ConcreteVisitor角色负责,因此完全不用修改ConcreteElement角色。

难增加 ConcreteElement角色

例如,假设现在要在示例中增加Entry类的子类Device类。即,Device类是File类和Directory类的兄弟类。
这时,我们需要在Visitor类中声明一个visit(Device)方法,并在所有的Visitor类的子类中都实现这个方法。

Visitor 工作所需的条件

“在 Visitor模式中,对数据结构中的元素进行处理的任务被分离出来,交给Visitor类负责。
这样,就实现了数据结构与处理的分离”这个主题。
但是有个前提条件:Element角色必须向Visitor角色公开足够多的信息。
例如示例中,visit(Directory)方法需要调用每个目录条目的accept方法。为此,Directory类必须提供用于获取每个目录条目的iterator方法。
访问者只有从数据结构中获取了足够多的信息后才能工作。这样缺点是,若公开了不应当被公开的信息,将来很难改良数据结构。

相关的设计模式

  • Iterator模式(第1章)
    Iterator模式和 Visitor模式都是在某种数据结构上进行处理。
    Iterator 模式用于逐个遍历保存在数据结构中的元素。
    Visitor 模式用于对保存在数据结构中的元素进行某种特定的处理。

  • Composite 模式(第11章)
    有时访问者所访问的数据结构会使用Composite模式。

  • Interpreter模式(第23章)
    在Interpreter模式中,有时会使用 Visitor模式。例如,在生成了语法树后,可能会使用 Visitor
    模式访问语法树的各个节点进行处理。

十四、Chain of Responsibility模式:推卸责任

Chain of Responsibility:职责链

例如,外部请求程序进行某个处理,但程序暂时无法直接决定由哪个对象负责处理时,就需要推卸责任。
这种情况下,我们可以考虑将多个对象组成一条职责链,然后按照它们在职责链上的顺序一个一个地找出到底应该谁来负责处理。

当一个人被要求做什么事情时,如果他可以做就自己做,如果不能做就将“要求”转给另外一个人。下一个人如果可以自己处理,就自己做;如果也不能自己处理,就再转给另外一个人…这就是Chain of Responsibility模式。

示例程序类图

在这里插入图片描述

注意 Support抽象类 的 support方法
如果resolve方法返回false,则support方法会将问题转交给下一个对象。
如果已经到达职责链中的最后一个对象,则表示没有人处理问题,将会显示出处理失败的相关信息。
在本例中我们只是简单地输出处理失败的相关信息,但根据需求不同,有时候也需要抛出异常。

Trouble

public class Trouble {private int number;             // 问题编号public Trouble(int number) {    // 生成问题this.number = number;}public int getNumber() {        // 获取问题编号return number;}public String toString() {      // 代表问题的字符串return "[Trouble " + number + "]";}
}

Support

public abstract class Support {private String name;                    // 解决问题的实例的名字private Support next;                   // 要推卸给的对象public Support(String name) {           // 生成解决问题的实例this.name = name;}public Support setNext(Support next) {  // 设置要推卸给的对象this.next = next;return next;}public void support(Trouble trouble) {  // 解决问题的步骤if (resolve(trouble)) {done(trouble);} else if (next != null) {next.support(trouble);} else {fail(trouble);}}public String toString() {              // 显示字符串return "[" + name + "]";}protected abstract boolean resolve(Trouble trouble); // 解决问题的方法protected void done(Trouble trouble) {  // 解决System.out.println(trouble + " is resolved by " + this + ".");}protected void fail(Trouble trouble) {  // 未解决System.out.println(trouble + " cannot be resolved.");}
}

NoSupport

public class NoSupport extends Support {public NoSupport(String name) {super(name);}protected boolean resolve(Trouble trouble) {     // 解决问题的方法return false; // 自己什么也不处理}
}

LimitSupport

public class LimitSupport extends Support {private int limit;                              // 可以解决编号小于limit的问题public LimitSupport(String name, int limit) {   // 构造函数super(name);this.limit = limit;}protected boolean resolve(Trouble trouble) {    // 解决问题的方法if (trouble.getNumber() < limit) {return true;} else {return false;}}
}

OddSupport

public class OddSupport extends Support {public OddSupport(String name) {                // 构造函数super(name);}protected boolean resolve(Trouble trouble) {    // 解决问题的方法if (trouble.getNumber() % 2 == 1) {return true;} else {return false;}}
}

SpecialSupport

public class SpecialSupport extends Support {private int number;                                 // 只能解决指定编号的问题public SpecialSupport(String name, int number) {    // 构造函数super(name);this.number = number;}protected boolean resolve(Trouble trouble) {        // 解决问题的方法if (trouble.getNumber() == number) {return true;} else {return false;}}
}

Main

public class Main {public static void main(String[] args) {Support alice   = new NoSupport("Alice");Support bob     = new LimitSupport("Bob", 100);Support charlie = new SpecialSupport("Charlie", 429);Support diana   = new LimitSupport("Diana", 200);Support elmo    = new OddSupport("Elmo");Support fred    = new LimitSupport("Fred", 300);// 形成职责链alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);// 制造各种问题for (int i = 0; i < 500; i += 33) {alice.support(new Trouble(i));}}
}

角色

在这里插入图片描述

  • Handler(处理者)
    定义处理请求的接口(API)。
    它知道“下一个处理者”是谁,如果自己无法处理请求,它会将请求转给“下一个处理者”(也是Handler角色)。
    示例中是Support类,负责处理请求的是support方法。

  • ConcreteHandler(具体的处理者)
    处理请求的具体角色。示例中是NoSupport、LimitSupport、OddSupport、SpecialSupport等各个类扮演此角色。

  • Client(请求者)
    向第一个ConcreteHandler角色发送请求的角色。示例中是Main类。

拓展思路的要点

弱化了发出请求的人(Client角色)和处理请求的人(ConcreteHandler角色)之间的关系

这是本模式最大优点。
如果不使用该模式,就必须有某个伟大的角色知道“谁应该处理什么请求”,这有点类似中央集权制。
而让“发出请求的人”知道“谁应该处理该请求”并不明智,会降低其作为可复用的组件的独立性。
补充说明:简单起见,示例中让扮演Client角色的Main类负责串联起ConcreteHandler的职责链。

可动态地改变职责链

示例中解决问题是按固定顺序进行处理的,但要考虑负责处理的各个ConcreteHandler角色之间的关系可能会发生变化的情况。
若使用本模式,通过委托推卸责任,可根据情况变化动态地重组职责链;
否则,在程序中固定写明“某个请求需要谁处理”这样的对应关系,很难在程序运行中去改变请求的处理者。
在视窗系统中,用户有时需要可以自由地在视窗中添加控件(按钮和文本输入框等),就很适合用本模式。

专注于自己的工作

每个ConcreteHandler角色都专注于自己所负责的处理。当自己无法处理时,会将请求转出去。
若不使用本模式,则需要编写一个“决定谁应该负责什么样的处理”的方法,亦或是让每个ConcreteHandler角色自己负责“任务分配”工作,
即“如果自己不能处理,就转交给那个人。如果他也不能处理,那就根据系统情况将请求再转交给另外一个人”。

推卸请求会导致处理延迟

与“事先确定哪个对象负责什么样的处理,当接收到请求时,立即让相应的对象去处理请求”相比,使用本模式确实导致处理请求发生了延迟。
需要权衡一下。若请求和处理者之间的关系是确定的,且需非常快的处理速度时,不使用本模式更好。

相关的设计模式

  • Composite 模式(第11章)
    Handler 角色经常会使用Composite模式。

  • Command模式(第23章)
    有时会使用Command模式向 Handler 角色发送请求。

相关文章:

《图解设计模式》笔记(六)访问数据结构

十三、Visitor 模式&#xff1a;访问数据结构并处理数据 Visitor&#xff1a;访问者 我们会“处理”在数据结构中保存着的元素&#xff0c;通常把“处理”代码放在表示数据结构的类中。 但每增加一种处理&#xff0c;就不得不去修改表示数据结构的类。 在 Visitor模式中&am…...

windows11上,使用pipx安装Poetry,Poetry的安装路径是什么?

当使用 pipx 安装 Poetry 时&#xff0c;pipx 会将 Poetry 安装到一个独立的虚拟环境中&#xff0c;并将其可执行文件链接到一个集中的目录中。以下是 pipx 安装 Poetry 时的路径信息&#xff1a; 1. Poetry 的安装路径 pipx 会为每个工具&#xff08;如 Poetry&#xff09;创…...

使用 vcpkg 简化 C++ 项目依赖管理

使用 vcpkg 简化 C 项目依赖管理 什么是 vcpkg&#xff1f; vcpkg 是微软推出的跨平台 C/C 包管理工具&#xff0c;支持 Windows/Linux/macOS。它可以帮助开发者&#xff1a; ✅ 一键安装 2000 开源库 ✅ 自动解决依赖关系 ✅ 生成 Visual Studio 集成配置 ✅ 支持自定义编译…...

怎样确定网站访问速度出现问题是后台还是服务器造成的?

网站的访问速度会影响到用户的体验感&#xff0c;当网络过于卡顿或访问速度较慢时&#xff0c;会给用户带来不好的体验感&#xff0c;但是网站访问速度不仅会是后台造成影响的&#xff0c;也可能是服务器的原因&#xff0c;那么我们该如何分辨呢&#xff1f; 当网站使用了数据库…...

【Elasticsearch】管道聚合

管道聚合就是在已有聚合结果之上在进行聚合&#xff0c;管道聚合是针对于聚合的聚合 在 Elasticsearch 中&#xff0c;管道聚合&#xff08;Pipeline Aggregations&#xff09;是一种特殊的聚合类型&#xff0c;用于对其他聚合的结果进行进一步的计算和处理&#xff0c;而不是直…...

CNN-GRU卷积神经网络门控循环单元多变量多步预测,光伏功率预测(Matlab完整源码和数据)

代码地址&#xff1a;CNN-GRU卷积神经网络门控循环单元多变量多步预测&#xff0c;光伏功率预测&#xff08;Matlab完整源码和数据) CNN-GRU卷积神经网络门控循环单元多变量多步预测&#xff0c;光伏功率预测 一、引言 1.1、研究背景和意义 随着全球能源危机和环境问题的日…...

后端java工程师经验之谈,工作7年,mysql使用心得

mysql 工作7年&#xff0c;mysql使用心得 mysql1.创建变量2.创建存储过程2.1&#xff1a;WHILE循环2.2&#xff1a;repeat循环2.3&#xff1a;loop循环2.4&#xff1a;存储过程&#xff0c;游标2.5&#xff1a;存储过程&#xff0c;有输入参数和输出参数 3.三种注释写法4.case …...

综合评价 | 基于随机变异系数-TOPSIS组合法的综合评价模型(Matlab)

基于随机变异系数-TOPSIS组合法的综合评价模型 代码获取私信回复&#xff1a;综合评价 | 基于随机变异系数-TOPSIS组合法的综合评价模型&#xff08;Matlab&#xff09; 一、引言 1.1、研究背景与意义 在现代社会&#xff0c;随着信息量的不断增加和数据复杂性的提升&#…...

Visual Studio Code中文出现黄色框子的解决办法

Visual Studio Code中文出现黄色框子的解决办法 一、vsCode中文出现黄色框子-如图二、解决办法 一、vsCode中文出现黄色框子-如图 二、解决办法 点击 “文件”点击 “首选项”点击 “设置” 搜索框直接搜索unicode选择“文本编辑器”&#xff0c;往下滑动&#xff0c;找到“Un…...

手写一个C++ Android Binder服务及源码分析

手写一个C Android Binder服务及源码分析 前言一、 基于C语言编写Android Binder跨进程通信Demo总结及改进二、C语言编写自己的Binder服务Demo1. binder服务demo功能介绍2. binder服务demo代码结构图3. binder服务demo代码实现3.1 IHelloService.h代码实现3.2 BnHelloService.c…...

【AIGC】在VSCode中集成 DeepSeek(OPEN AI同理)

在 Visual Studio Code (VSCode) 中集成 AI 编程能力&#xff0c;可以通过安装和配置特定插件来实现。以下是如何通过 Continue 和 Cline 插件集成 DeepSeek&#xff1a; 一、集成 DeepSeek 获取 DeepSeek API 密钥&#xff1a;访问 DeepSeek 官方网站&#xff0c;注册并获取 …...

使用 Three.js 实现热力渐变效果

大家好&#xff01;我是 [数擎 AI]&#xff0c;一位热爱探索新技术的前端开发者&#xff0c;在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情&#xff0c;欢迎关注我的文章&#xff0c;我们一起成长、进步&#xff01; 开发领域&#xff1a;前端开发 | A…...

Vue事件处理 - 绑定事件

Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue事件处理 - 绑定事件及事件处理 目录 事件处理 绑定方式 函数表达式 绑定函数名 输入框绑定事件 拿到输入框的值 传值加事件源 事件第三种写法 总结 事件处理 绑定方式 函数表达式 在按钮上使用函数表达式绑定事…...

DVWA靶场通关——SQL Injection篇

一&#xff0c;Low难度下unionget字符串select****注入 1&#xff0c;首先手工注入判断是否存在SQL注入漏洞&#xff0c;输入1 这是正常回显的结果&#xff0c;再键入1’ You have an error in your SQL syntax; check the manual that corresponds to your MySQL server ver…...

DeepSeek 助力 Vue 开发:打造丝滑的步骤条

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

今日学习总结

1.完成了P2242公路维修问题 2.完成了P10605下头论文 1.P2242 思考&#xff1a;建立单向链表&#xff0c;使用qsort降序排序。 #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<string.h> int n,m; int a[15005],b[15005],ans;…...

Transformer 的辉煌与大模型方向确立,点燃AGI之火把

GPT3&#xff0c;指明大模型发展方向&#xff0c;点燃大模型软件行业繁荣之火&#xff0c;目前大模型有100万个。 DeepSeek-V3&#xff0c;指明下一个阶段大模型发张方向&#xff0c;破壁&#xff1a; 资金壁垒&#xff1a;训练成本降低&#xff0c;适配丰富硬件&#xff0c;总…...

DeepSeek-Coder系列模型:智能编程助手的未来

文章目录 一、模型架构与核心功能1. 模型架构2. 核心功能 二、多语言支持与代码生成1. Python代码生成2. Java代码生成3. C代码生成4. JavaScript代码生成 三、仓库级代码理解1. 代码结构分析2. 上下文理解 四、FIM填充技术1. 函数自动填充2. 代码补全 五、应用场景1. 代码补全…...

微信小程序longpress以及touchend的bug,touchend不触发,touchend不执行

核心原因&#xff1a;bind&#xff1a;touchend里面不能放wx:if 举例&#xff1a; <view bind:longpress"longpressBtn" bind:touchend"touchendBtn"><view wx:if"{{isRecording}}" >松开发送</view><view wx:else"…...

多租户架构设计与实现:基于 PostgreSQL 和 Node.js

多租户架构设计与实现:基于 PostgreSQL 和 Node.js 引言 多租户架构(Multi-tenancy)是现代 SaaS(Software as a Service)应用的核心设计模式之一。它允许多个租户共享同一套应用实例,同时确保数据隔离和安全性。本文将详细介绍多租户架构的设计方案,并基于 PostgreSQL…...

四、OSG学习笔记-基础图元

前一章节&#xff1a; 三、OSG学习笔记-应用基础-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145514021 代码&#xff1a;CuiQingCheng/OsgStudy - Gitee.com 一、绘制盒子模型 下面一个简单的 demo #include<windows.h> #include<osg/Node&…...

windows平台本地部署DeepSeek大模型+Open WebUI网页界面(可以离线使用)

环境准备: 确定部署方案请参考:DeepSeek-R1系列(1.5b/7b/8b/32b/70b/761b)大模型部署需要什么硬件条件-CSDN博客 根据本人电脑配置:windows11 + i9-13900HX+RTX4060+DDR5 5600 32G内存 确定部署方案:DeepSeek-R1:7b + Ollama + Open WebUI 1. 安装 Ollama Ollama 是一…...

功能架构元模型

功能架构的元模型是对功能架构进行描述和建模的基础框架,它有助于统一不同团队对系统的理解,并为系统的设计和开发提供一致的标准和规范。虽然具体的元模型可能因不同的应用领域和特定需求而有所差异,但一般来说,功能架构的元模型可以涵盖以下几个方面: 组件/模块元模型:…...

云计算——AWS Solutions Architect – Associate(saa)4.安全组和NACL

安全组一充当虚拟防火墙对于关联实例&#xff0c;在实例级别控制入站和出站流量。 网络访问控制列表(NACL)一充当防火墙关联子网&#xff0c;在子网级别控制入站和出站流量。 在专有网络中&#xff0c;安全组和网络ACL(NACL)一起帮助构建分层网络防御。 安全组在实例级别操作…...

Fiddler Classic(HTTP流量代理+半汉化)

目录 一、关于Fiddler (一) Fiddler Classic (二) Fiddler Everywhere (三) Fiddler Everywhere Reporter (四) FiddlerCore (五) 总结 二、 软件安全性 1. 软件安装包 2. 软件汉化dll 三、安装与半汉化 1. 正常打开安装包点击下一步安装即可&#xff0c;安装路径自…...

【hive】记一次hiveserver内存溢出排查,线程池未正确关闭导致

一、使用 MemoryAnalyzer软件打开hprof文件 很大有30G&#xff0c;win内存24GB&#xff0c;不用担心可以打开&#xff0c;ma软件能够生成索引文件&#xff0c;逐块分析内存&#xff0c;如下图。 大约需要4小时。 overview中开不到具体信息。 二、使用Leak Suspects功能继续…...

MySQL的字段类型

MySQL 字段类型可以简单分为三大类 数值类型&#xff1a;整型&#xff08;TINYINT、SMALLINT、MEDIUMINT、INT 和 BIGINT&#xff09;、浮点型&#xff08;FLOAT 和 DOUBLE&#xff09;、定点型&#xff08;DECIMAL&#xff09;字符串类型&#xff1a;CHAR、VARCHAR、TINYTEXT…...

HTML之JavaScript运算符

HTML之JavaScript运算符 1.算术运算符 - * / %除以0&#xff0c;结果为Infinity取余数&#xff0c;如果除数为0&#xff0c;结果为NaN NAN:Not A Number2.复合赋值运算符 - * / %/ 除以0&#xff0c;结果为Infinity% 如果除数为0&#xff0c;结果为NaN NaN:No…...

UE5--浅析委托原理(Delegate)

委托概述 委托是一种用于事件处理的机制。通过使用委托,可以将一个或多个函数绑定到一个事件上,在事件触发时自动调用这些函数。代理也叫做委托,比如:跳,跑,开枪,伤害等响应,就是注册一个委托回调,其作用就是提供一种消息机制,都知道消息的传递需要发送方和接收方,…...

Android13-系统服务大管家-ServiceManager进程-启动篇

文章目录 关注 ServiceMager 原因ServerManager需要掌握的知识资料参考ServiceManager 进程启动启动脚本涉及到的相关源码文件源码跟踪ServiceManager脚本启动位置ServiceManager关联脚本 Native层源码分析main.cpp流程打开驱动 initWithDriverinitmakeProcessState 构造方法op…...

网络安全溯源 思路 网络安全原理

网络安全背景 网络就是实现不同主机之间的通讯。网络出现之初利用TCP/IP协议簇的相关协议概念&#xff0c;已经满足了互连两台主机之间可以进行通讯的目的&#xff0c;虽然看似简简单单几句话&#xff0c;就描述了网络概念与网络出现的目的&#xff0c;但是为了真正实现两台主机…...

Mac(m1)本地部署deepseek-R1模型

1. 下载安装ollama 直接下载软件&#xff0c;下载完成之后&#xff0c;安装即可&#xff0c;安装完成之后&#xff0c;命令行中可出现ollama命令 2. 在ollama官网查看需要下载的模型下载命令 1. 在官网查看deepseek对应的模型 2. 选择使用电脑配置的模型 3. copy 对应模型的安…...

从零复现DeepSeek R1:从V3中对MoE、MLA、MTP的实现,到Open R1对R1中SFT、GRPO的实现

前言 虽然我司从23年起&#xff0c;便逐步从教育为主转型到了科技为主&#xff0c;但不代表教育业务便没有了 随着DeepSeek特别是R1、其次V3模型的大火&#xff0c;我司七月在线的大模型线上营群里一学员朋友DIFY问道&#xff1a;校长好&#xff0c;deepseek 的课程目前有多少…...

[EAI-033] SFT 记忆,RL 泛化,LLM和VLM的消融研究

Paper Card 论文标题&#xff1a;SFT Memorizes, RL Generalizes: A Comparative Study of Foundation Model Post-training 论文作者&#xff1a;Tianzhe Chu, Yuexiang Zhai, Jihan Yang, Shengbang Tong, Saining Xie, Dale Schuurmans, Quoc V. Le, Sergey Levine, Yi Ma 论…...

示例代码:C# MQTTS双向认证(客户端)(服务器EMQX)

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

自制游戏——斗罗大陆

很简陋&#xff0c;没有图&#xff0c;请见谅 // mine[0] 级数 // mine[1] 战力 //mine[2] 1 白虎 //mine[2] 2 昊天锤 //mine[2] 3 蓝银草 #include <bits/stdc.h> using namespace std; int mine[100],live3, dou 1, luo 1, da 1, bag[1000], huan 0, lia…...

数据治理双证通关经验分享 | CDGA/CDGP备考全指南

历经1个月多的系统准备&#xff0c;本人于2024年顺利通过DAMA China的CDGA&#xff08;数据治理工程师&#xff09;和CDGP&#xff08;数据治理专家&#xff09;双认证。现将备考经验与资源体系化整理&#xff0c;助力从业者高效通关。 &#x1f31f; 认证价值与政策背景 根据…...

Vue全流程--Vue3.0与Vue2.0响应式原理对比

Vue2中数据的响应式 需要使用Vue.set这么一个api&#xff0c;修改数据 需要使用Vue.delete这么一个api&#xff0c;删除数据 数据代理这个当面的理解可以看看我前面文章Vue全流程--数据代理的理解以及在Vue中的应用-CSDN博客 Vue3中数据的响应式 Vue3使用proxy这个api实现…...

Spring中都应用了哪些设计模式?

好的&#xff01;以下是您提到的八种设计模式在 Spring 中的简单示例&#xff1a; 1. 简单工厂模式 简单工厂模式通过传入参数来决定实例化哪个类。Spring 中的 BeanFactory 就是简单工厂模式的应用。 示例代码&#xff1a; // 1. 创建接口和具体实现类 public interface A…...

fastjson2学习大纲

一、基础篇 - JSON与fastjson2核心概念 JSON基础 JSON语法规范&#xff08;RFC 8259&#xff09;JSON数据类型与Java类型对应关系序列化/反序列化核心概念 fastjson2入门 与fastjson1的主要区别核心优势&#xff1a; 性能提升&#xff08;JSONB二进制协议&#xff09;更完善的…...

k8s部署elasticsearch

前置环境:已部署k8s集群,ip地址为 192.168.10.1~192.168.10.5,总共5台机器。 1. 创建provisioner制备器(如果已存在,则不需要) 制备器的具体部署方式,参考我之前的文章:k8s部署rabbitmq-CSDN博客 2. 编写wms-elk-data-sc.yaml配置文件 apiVersion: storage.k8s.io/…...

BS架构(笔记整理)

楔子.基本概念 1.在网络架构中&#xff1a; 服务器通常是集中式计算资源&#xff0c;负责处理和存储数据&#xff1b;客户机是请求这些服务的终端设备&#xff0c;可能是个人电脑或移动设备&#xff1b;浏览器则是客户机上用来与服务器交互的工具&#xff0c;负责展示网页内容…...

从基础到人脸识别与目标检测

前言 从本文开始&#xff0c;我们将开始学习ROS机器视觉处理&#xff0c;刚开始先学习一部分外围的知识&#xff0c;为后续的人脸识别、目标跟踪和YOLOV5目标检测做准备工作。我采用的笔记本是联想拯救者游戏本&#xff0c;系统采用Ubuntu20.04&#xff0c;ROS采用noetic。 颜…...

ArcGIS Pro SDK (二十七)自定义许可

ArcGIS Pro SDK (二十七)自定义许可 环境:Visual Studio 2022 + .NET6 + ArcGIS Pro SDK 3.0 文章目录 ArcGIS Pro SDK (二十七)自定义许可1 在Config.xaml中添加扩展配置2 在Module1.cs中实现接口IExtensionConfig1 在Config.xaml中添加扩展配置 <modules><inse…...

一、kubernetes k8s

k8s概述: k8s的全称:kubernetes k8s k8s的版本:1.30 1.20------------用的最多的版本&#xff0c;1.18-1.21 1.24------------>k8s的镜像不再使用docker&#xff0c;containerd k8s的作用&#xff1a; 用于自动部署&#xff0c;自动扩展和管理“容器化应…...

C#、.Net 中级高级架构管理面试题杂烩

1、简述值类型和引用类型的区别 存储位置&#xff1a;值类型变量直接存储数据的值&#xff0c;通常存储在栈上&#xff1b;引用类型变量存储的是对象在堆上的引用地址。 内存管理&#xff1a;值类型的内存由系统自动管理&#xff0c;当超出作用域时自动释放&#xff1b;引用类…...

ArrayList和LinkedList有什么区别?在什么情况下使用ArrayList更高效?

ArrayList和LinkedList在Java中是两种常用的数据结构&#xff0c;分别基于数组和链表实现。它们在性能、内存使用和适用场景上各有特点。 ArrayList与LinkedList的主要区别 数据结构&#xff1a; ArrayList&#xff1a;基于动态数组实现&#xff0c;元素存储在连续的内存空间…...

KITE提示词框架:引导大语言模型的高效新工具

大语言模型的应用日益广泛。然而&#xff0c;如何确保这些模型生成的内容在AI原生应用中符合预期&#xff0c;仍是一个需要不断探索的问题。以下内容来自于《AI 原生应用开发&#xff1a;提示工程原理与实战》一书&#xff08;京东图书&#xff1a;https://item.jd.com/1013604…...

Spring 整合 MyBatis:核心知识点详解

一、Spring 整合 MyBatis 的优势 依赖注入&#xff1a;Spring 的 IOC 容器可以管理 MyBatis 的组件&#xff08;如 SqlSessionFactory、Mapper 接口等&#xff09;&#xff0c;减少手动创建对象的繁琐。 事务管理&#xff1a;Spring 提供了声明式事务管理&#xff0c;可以轻松…...

centos docker安装

一、前置条件 安装gcc和c: yum -y install gcc yum -y install gcc-c 二、卸载旧版本 如果之前安装过Docker&#xff0c;需要先卸载旧版本&#xff1a; sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logr…...