瑞_23种设计模式_访问者模式
文章目录
- 1 访问者模式(Visitor Pattern)
- 1.1 介绍
- 1.2 概述
- 1.3 访问者模式的结构
- 1.4 访问者模式的优缺点
- 1.5 访问者模式的使用场景
- 2 案例一
- 2.1 需求
- 2.2 代码实现
- 3 案例二
- 3.1 需求
- 3.2 代码实现
- 4 拓展——双分派
- 4.1 分派
- 4.2 动态分派(多态)
- 4.3 静态分派(重载)
- 4.4 双分派
🙊 前言:本文章为瑞_系列专栏之《23种设计模式》的访问者模式篇。本文中的部分图和概念等资料,来源于博主学习设计模式的相关网站《菜鸟教程 | 设计模式》和《黑马程序员Java设计模式详解》,特此注明。本文中涉及到的软件设计模式的概念、背景、优点、分类、以及UML图的基本知识和设计模式的6大法则等知识,建议阅读 《瑞_23种设计模式_概述》
本系列 - 设计模式 - 链接:《瑞_23种设计模式_概述》
⬇️本系列 - 创建型模式 - 链接🔗单例模式:《瑞_23种设计模式_单例模式》
工厂模式:《瑞_23种设计模式_工厂模式》
原型模式:《瑞_23种设计模式_原型模式》
抽象工厂模式:《瑞_23种设计模式_抽象工厂模式》
建造者模式:《瑞_23种设计模式_建造者模式》⬇️本系列 - 结构型模式 - 链接🔗
代理模式:《瑞_23种设计模式_代理模式》
适配器模式:《瑞_23种设计模式_适配器模式》
装饰者模式:《瑞_23种设计模式_装饰者模式》
桥接模式:《瑞_23种设计模式_桥接模式》
外观模式:《瑞_23种设计模式_外观模式》
组合模式:《瑞_23种设计模式_组合模式》
享元模式:《瑞_23种设计模式_享元模式》⬇️本系列 - 行为型模式 - 链接🔗
模板方法模式:《瑞_23种设计模式_模板方法模式》
策略模式:《瑞_23种设计模式_策略模式》
命令模式:《瑞_23种设计模式_命令模式》
职责链模式:《瑞_23种设计模式_职责链模式》
状态模式:《瑞_23种设计模式_状态模式》
观察者模式:《瑞_23种设计模式_观察者模式》
中介者模式:《瑞_23种设计模式_中介者模式》
迭代器模式:《瑞_23种设计模式_迭代器模式》
访问者模式:《后续更新》
备忘录模式:《后续更新》
解释器模式:《后续更新》

1 访问者模式(Visitor Pattern)
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
瑞:行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。
瑞:行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。
访问者模式属于:对象行为模式
1.1 介绍
-
意图:主要将数据结构与数据操作分离。
-
主要解决:稳定的数据结构和易变的操作耦合问题。
-
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,使用访问者模式将这些封装到类中。
-
如何解决:在被访问的类里面加一个对外提供接待访问者的接口。
-
关键代码:在数据基础类里面有一个方法接受访问者,将自身引用传入访问者。
-
应用实例:
您在朋友家做客,您是访问者,朋友接受您的访问,您通过朋友的描述,然后对朋友的描述做出一个判断,这就是访问者模式。 -
优点:
1️⃣ 符合单一职责原则。
2️⃣ 优秀的扩展性。
3️⃣ 灵活性。 -
缺点:
1️⃣ 具体元素对访问者公布细节,违反了迪米特原则。
2️⃣ 具体元素变更比较困难。
3️⃣ 违反了依赖倒置原则,依赖了具体类,没有依赖抽象。 -
使用场景:
1️⃣ 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。
2️⃣ 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类,也不希望在增加新操作时修改这些类。 -
注意事项:
1️⃣ 访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。
1.2 概述
定义:封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新的操作。
访问者模式的主要思想是将一些作用于某种数据结构中的各元素的操作封装起来,使得可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
在访问者模式中,针对系统中拥有固定类型数的对象结构(元素),在其内提供一个accept()方法来接受访问者对象的访问。不同的访问者对同一个元素的访问内容是不同的,这使得相同的元素集合可以产生不同的数据结果。
1.3 访问者模式的结构
- 访问者模式主要包含以下角色:
1️⃣ 抽象访问者(Visitor)角色:定义了对每一个元素(Element)访问的行为,它的参数就是可以访问的元素,它的方法个数理论上来讲与元素类个数(Element的实现类个数)是一样的,从这点不难看出,访问者模式要求元素类的个数不能改变。
2️⃣ 具体访问者(ConcreteVisitor)角色:给出对每一个元素类访问时所产生的具体行为。
3️⃣ 抽象元素(Element)角色:定义了一个接受访问者的方法(accept),其意义是指,每一个元素都要可以被访问者访问。
4️⃣ 具体元素(ConcreteElement)角色: 提供接受访问方法的具体实现,而这个具体的实现,通常情况下是使用访问者提供的访问该元素类的方法。
5️⃣ 对象结构(Object Structure)角色:定义当中所提到的对象结构,对象结构是一个抽象表述,具体点可以理解为一个具有容器性质或者复合对象特性的类,它会含有一组元素(Element),并且可以迭代这些元素,供访问者访问。
1.4 访问者模式的优缺点
优点:
-
扩展性好
在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。 -
复用性好
通过访问者来定义整个对象结构通用的功能,从而提高复用程度。 -
分离无关行为
通过访问者来分离无关的行为,把相关的行为封装在一起,构成一个访问者,这样每一个访问者的功能都比较单一。
缺点:
-
对象结构变化很困难
在访问者模式中,每增加一个新的元素类,都要在每一个具体访问者类中增加相应的具体操作,这违背了“开闭原则”。 -
违反了依赖倒置原则
访问者模式依赖了具体类,而没有依赖抽象类。
1.5 访问者模式的使用场景
- 对象结构相对稳定,但其操作算法经常变化的程序。
- 对象结构中的对象需要提供多种不同且不相关的操作,而且要避免让这些操作的变化影响对象的结构。
2 案例一
【案例】给宠物喂食
2.1 需求
现在养宠物的人特别多,我们就以这个为例,当然宠物还分为狗,猫等,要给宠物喂食的话,主人可以喂,其他人也可以喂食。
- 访问者角色:给宠物喂食的人
- 具体访问者角色:主人、其他人
- 抽象元素角色:动物抽象类
- 具体元素角色:宠物狗、宠物猫
- 结构对象角色:主人家
类图如下:

2.2 代码实现
创建抽象访问者接口
/*** 抽象访问者角色类** @author LiaoYuXing-Ray**/
public interface Person {// 喂食宠物狗void feed(Cat cat);// 喂食宠物猫void feed(Dog dog);
}
创建不同的具体访问者角色(主人和其他人),都需要实现 Person接口
/*** 具体访问者角色类(自己)** @author LiaoYuXing-Ray**/
public class Owner implements Person {public void feed(Cat cat) {System.out.println("主人喂食猫");}public void feed(Dog dog) {System.out.println("主人喂食狗");}
}
/*** 具体访问者角色类(其他人)** @author LiaoYuXing-Ray**/
public class Someone implements Person {public void feed(Cat cat) {System.out.println("其他人喂食猫");}public void feed(Dog dog) {System.out.println("其他人喂食狗");}
}
定义抽象节点 – 宠物
/*** 抽象元素角色类** @author LiaoYuXing-Ray**/
public interface Animal {// 接受访问者访问的功能void accept(Person person);
}
定义实现Animal接口的 具体节点(元素)
/*** 具体元素角色类(宠物猫)** @author LiaoYuXing-Ray**/
public class Cat implements Animal {public void accept(Person person) {person.feed(this);// 访问者给宠物猫喂食System.out.println("好好吃,喵喵喵。。。");}
}
/*** 具体元素角色类(宠物狗)** @author LiaoYuXing-Ray**/
public class Dog implements Animal {public void accept(Person person) {person.feed(this);// 访问者给宠物猫喂食System.out.println("好好吃,汪汪汪。。。");}
}
定义对象结构,此案例中就是主人的家
import java.util.ArrayList;
import java.util.List;/*** 对象结构类** @author LiaoYuXing-Ray**/
public class Home {// 声明一个集合对象,用来存储元素对象private final List<Animal> nodeList = new ArrayList<Animal>();// 添加元素功能public void add(Animal animal) {nodeList.add(animal);}public void action(Person person) {// 遍历集合,获取每一个元素,让访问者访问每一个元素for (Animal animal : nodeList) {animal.accept(person);}}
}
/*** 测试类** @author LiaoYuXing-Ray**/
public class Client {public static void main(String[] args) {// 创建Home对象Home home = new Home();//添加元素到Home对象中home.add(new Dog());home.add(new Cat());// 创建主人对象Owner owner = new Owner();Someone someone = new Someone();// 让主人喂食所有的宠物home.action(owner);home.action(someone);}
}
代码运行结果如下:
主人喂食狗好好吃,汪汪汪。。。主人喂食猫好好吃,喵喵喵。。。其他人喂食狗好好吃,汪汪汪。。。其他人喂食猫好好吃,喵喵喵。。。
3 案例二
本案例为菜鸟教程中的案例
3.1 需求
我们将创建一个定义接受操作的 ComputerPart 接口。Keyboard、Mouse、Monitor 和 Computer 是实现了 ComputerPart 接口的实体类。我们将定义另一个接口 ComputerPartVisitor,它定义了访问者类的操作。Computer 使用实体访问者来执行相应的动作。
VisitorPatternDemo,我们的演示类使用 Computer、ComputerPartVisitor 类来演示访问者模式的用法。

3.2 代码实现
步骤 1
定义一个表示元素的接口。
public interface ComputerPart {public void accept(ComputerPartVisitor computerPartVisitor);
}
步骤 2
创建扩展了上述类的实体类。
public class Keyboard implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
public class Monitor implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
public class Mouse implements ComputerPart {@Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {computerPartVisitor.visit(this);}
}
public class Computer implements ComputerPart {ComputerPart[] parts;public Computer(){parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()}; } @Overridepublic void accept(ComputerPartVisitor computerPartVisitor) {for (int i = 0; i < parts.length; i++) {parts[i].accept(computerPartVisitor);}computerPartVisitor.visit(this);}
}
步骤 3
定义一个表示访问者的接口。
public interface ComputerPartVisitor {public void visit(Computer computer);public void visit(Mouse mouse);public void visit(Keyboard keyboard);public void visit(Monitor monitor);
}
步骤 4
创建实现了上述类的实体访问者。
public class ComputerPartDisplayVisitor implements ComputerPartVisitor {@Overridepublic void visit(Computer computer) {System.out.println("Displaying Computer.");}@Overridepublic void visit(Mouse mouse) {System.out.println("Displaying Mouse.");}@Overridepublic void visit(Keyboard keyboard) {System.out.println("Displaying Keyboard.");}@Overridepublic void visit(Monitor monitor) {System.out.println("Displaying Monitor.");}
}
步骤 5
使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。
public class VisitorPatternDemo {public static void main(String[] args) {ComputerPart computer = new Computer();computer.accept(new ComputerPartDisplayVisitor());}
}
步骤 6
执行程序,输出结果:
Displaying Mouse.Displaying Keyboard.Displaying Monitor.Displaying Computer.
4 拓展——双分派
访问者模式用到了一种双分派的技术。
4.1 分派
变量被声明时的类型叫做变量的静态类型,有些人又把静态类型叫做明显类型;而变量所引用的对象的真实类型又叫做变量的实际类型。比如 Map map = new HashMap() ,map变量的静态类型是 Map ,实际类型是 HashMap 。根据对象的类型而对方法进行的选择,就是分派(Dispatch),分派(Dispatch)又分为两种,即静态分派和动态分派。
-
静态分派(Static Dispatch) :发生在编译时期,分派根据静态类型信息发生。静态分派对于我们来说并不陌生,方法重载就是静态分派。
-
动态分派(Dynamic Dispatch): 发生在运行时期,动态分派动态地置换掉某个方法。Java通过方法的重写(多态)支持动态分派。
4.2 动态分派(多态)
通过方法的重写(多态)支持动态分派。
public class Animal {public void execute() {System.out.println("Animal");}
}public class Dog extends Animal {@Overridepublic void execute() {System.out.println("dog");}
}public class Cat extends Animal {@Overridepublic void execute() {System.out.println("cat");}
}public class Client {public static void main(String[] args) {Animal a = new Dog();a.execute();Animal a1 = new Cat();a1.execute();}
}
执行程序,输出结果:
dogcat
上面代码的结果大家应该直接可以说出来,这不就是多态吗!运行执行的是子类中的方法。
Java编译器在编译时期并不总是知道哪些代码会被执行,因为编译器仅仅知道对象的静态类型,而不知道对象的真实类型;而方法的调用则是根据对象的真实类型,而不是静态类型。
4.3 静态分派(重载)
通过方法重载支持静态分派。
public class Animal {
}public class Dog extends Animal {
}public class Cat extends Animal {
}public class Execute {public void execute(Animal a) {System.out.println("Animal");}public void execute(Dog d) {System.out.println("dog");}public void execute(Cat c) {System.out.println("cat");}
}public class Client {public static void main(String[] args) {Animal a = new Animal();Animal a1 = new Dog();Animal a2 = new Cat();Execute exe = new Execute();exe.execute(a);exe.execute(a1);exe.execute(a2);}
}
执行程序,输出结果:
AnimalAnimalAnimal
这个结果可能出乎一些你的意料了吧~
因为重载方法的分派是根据静态类型进行的,这个分派过程在编译时期就完成了。
4.4 双分派
所谓双分派技术就是在选择一个方法的时候,不仅仅要根据消息接收者(receiver)的运行时区别,还要根据参数的运行时区别。
public class Animal {public void accept(Execute exe) {exe.execute(this);}
}public class Dog extends Animal {public void accept(Execute exe) {exe.execute(this);}
}public class Cat extends Animal {public void accept(Execute exe) {exe.execute(this);}
}public class Execute {public void execute(Animal a) {System.out.println("animal");}public void execute(Dog d) {System.out.println("dog");}public void execute(Cat c) {System.out.println("cat");}
}public class Client {public static void main(String[] args) {Animal a = new Animal();Animal d = new Dog();Animal c = new Cat();Execute exe = new Execute();a.accept(exe);d.accept(exe);c.accept(exe);}
}
在上面代码中,客户端将 Execute 对象做为参数传递给 Animal 类型的变量调用的方法,这里完成第一次分派,这里是方法重写,所以是动态分派,也就是执行实际类型中的方法,同时也将自己this作为参数传递进去,这里就完成了第二次分派,这里的 Execute 类中有多个重载的方法,而传递进行的是this,就是具体的实际类型的对象。
说到这里,我们已经明白双分派是怎么回事了,但是它有什么效果呢?就是可以实现方法的动态绑定,我们可以对上面的程序进行修改。运行结果如下:
执行程序,输出结果:
animaldogcat
双分派实现动态绑定的本质,就是在重载方法委派的前面加上了继承体系中覆盖的环节,由于覆盖是动态的,所以重载就是动态的了
如果觉得这篇文章对您有所帮助的话,请动动小手点波关注💗,你的点赞👍收藏⭐️转发🔗评论📝都是对博主最好的支持~
相关文章:
瑞_23种设计模式_访问者模式
文章目录 1 访问者模式(Visitor Pattern)1.1 介绍1.2 概述1.3 访问者模式的结构1.4 访问者模式的优缺点1.5 访问者模式的使用场景 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 拓展——双分派4.1 分派4.2 动态分派(多态&am…...
Docker网络代理配置 可能埋下的坑
Docker 网络代理配置 1. 在 /etc/systemd/system 目录下创建 docker.service.d 目录 sudo mkdir -p /etc/systemd/system/docker.service.d2. 在/etc/systemd/system/docker.service.d下创建 http-proxy.conf 文件 sudo touch /etc/systemd/system/docker.service.d/http-pr…...
外包干了3天,技术退步明显.......
先说一下自己的情况,大专生,19年通过校招进入杭州某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…...
分布式向量数据库-安装部署
下载 GitHub - pgvector/pgvector: Open-source vector similarity search for Postgres 源码编译 ##文件解压缩 unzip pgvector-0.6.2.zip ##编译 make && make install 功能验证 #安装扩展CREATE EXTENSION vector;#创建测试表CREATE TABLE items (id bigseri…...
【深入理解计算机系统第3版】有符号数和无符号数转换以及移位运算练习题2.23
题目 考虑下面的C函数: int fun1(unsigned word) {return (int) ((word << 24) >> 24); }int fun2(unsigned word) {return ((int) word << 24) >> 24; } 假设一个采用补码运算的机器上以32位程序来执行这些函数。还假设有符号数值的右移…...
Linux函数学习 epoll
1、Linux epoll函数 1.1、创建epoll实例 int epoll_create1(int flag); 返回值:-1 失败,非负数 成功 flag :默认传入0 1.2、管理epoll对象 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); epfd :e…...
2024年4月12日 十二生肖 今日运势
小运播报:2024年4月12日,星期五,农历三月初四 (甲辰年戊辰月丙午日),法定工作日。 红榜生肖:羊、狗、虎 需要注意:牛、马、鼠 喜神方位:西南方 财神方位:…...
代码随想录第36、37天| 435. 无重叠区间 763.划分字母区间 56. 合并区间
435. 无重叠区间 435. 无重叠区间 - 力扣(LeetCode) 代码随想录 (programmercarl.com) 贪心算法,依然是判断重叠区间 | LeetCode:435.无重叠区间_哔哩哔哩_bilibili 给定一个区间的集合 intervals ,其中 intervals[…...
代码学习记录40---动态规划
随想录日记part40 t i m e : time: time: 2024.04.10 主要内容:今天开始要学习动态规划的相关知识了,今天的内容主要涉及: 买卖股票的最佳时机加强版。 123.买卖股票的最佳时机III 188.买卖股票的最佳时机…...
java八股——消息队列MQ
上一篇传送门:点我 目前只学习了RabbitMQ,后续学习了其他MQ后会继续补充。 MQ有了解过吗?说说什么是MQ? MQ是Message Queue的缩写,也就是消息队列的意思。它是一种应用程序对应用程序的通信方法,使得应用…...
【前端Vue】Vue3+Pinia小兔鲜电商项目第5篇:整体认识和路由配置,本资源由 收集整理【附代码文档】
Vue3ElementPlusPinia开发小兔鲜电商项目完整教程(附代码资料)主要内容讲述:认识Vue3,使用create-vue搭建Vue3项目1. Vue3组合式API体验,2. Vue3更多的优势,1. 认识create-vue,2. 使用create-vue创建项目,1. setup选项的写法和执行…...
前端项目部署教程——有域名无证书
一、拉取nginx镜像 docker pull nginx //先拉取nginx镜像二、打包前端项目 1、将Vue打包项目传输到/usr/local/vue/下blog和admin文件夹下 2、在/usr/local/nginx下创建nginx.conf文件,格式如下: events {worker_connections 1024; }http {include …...
后端项目部署教程
一、打包jar包 lyamanoblog-server-0.0.1.jar ps:运行时可能会提醒不能有大写字母,所以用的都是小写字母 二、编写Dockerfile文件 FROM java:8 VOLUME /tmp ADD lyamanoblog-server-0.0.1.jarblog.jar ENTRYPOINT ["java","-Djava.securit…...
【微命令】git 如何修改某个分支的名字(git branch -m newbranch)
简要信息,快速记录 命令 # 切换到某个需要修改的分支 git checkout oldbranch# 修改分支名字 git branch -m newbranch假设作为git设计者,要用来修改branch的命令,那么就是 git branch作为前缀,然后进一步修改的命令是branch相关…...
Unity UI 优化技巧
将画布分割为多个 问题:当 UI Canvas 的任何元素发生变化时,都会影响整个 Canvas。 Canvas 是 Unity UI 的重要组成部分。它创建一个网格来表示放置在其顶部的 UI 元素,在 UI 元素更改时重建网格,并调用 GPU 来渲染实际的用户界面。 创建这些网络可能非常昂贵。UI 元素应…...
前端学习之DOM编程案例:抽奖案例
代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>抽奖案例</title><style>*{margin: 0;padding: 0;}</style> </head> <body><div id"container"&g…...
解决windows下Qt Creator显示界面过大的问题
🐌博主主页:🐌倔强的大蜗牛🐌 📚专栏分类:QT❤️感谢大家点赞👍收藏⭐评论✍️ 目录 问题描述 解决方法 1、右击此电脑--->属性 2、点击高级系统设置--->点击环境变量 3、 找到系…...
MySQL 通信协议 tcp c/s架构 jdbc java
简介 服务器启动后,会使用 TCP 监听一个本地端口,当客户端的连接请求到达时,就会执行三段握手以及 MySQL 的权限验证;验证成功后,客户端开始发送请求,服务器会以响应的报文格式返回数据;当客户…...
蓝桥杯第十三届电子类单片机组决赛程序设计
前言 一、决赛题目 1.比赛题目 2.题目解读 二、功能实现 1.关于定时器资源 1)超声波和NE555需要的定时器资源 2)定时器2 2.单位切换 3.数据长度不足时,高位熄灭 4.AD/DA多通道的处理 5.PWM输出 6.长按功能的实现 三、完整代码演…...
【Entity Framework】如何使用EF中的生成值
【Entity Framework】如何使用EF中的生成值 文章目录 【Entity Framework】如何使用EF中的生成值一、概述二、默认值三、计算列四、设置主键五、显示配置值生成六、设置日期/时间值生成6.1 创建时间戳6.2 更新时间戳 七、替代值生成八、无值生成九、总结 一、概述 数据库列的值…...
【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
