深入理解JavaScript设计模式之原型模式

目录

    • 前言引入原型模式
      • 头脑风暴
      • 传统方式 vs 原型模式
      • 实战案例:飞机大战中的分身术
    • 原型模式实现的关键秘密
      • 实战演练:造一架能分身的飞机
      • 克隆是创建对象的手段
      • 原型模式:轻装上阵的造物术
    • 原型编程范型的一些规则
        • 原型编程的四大门规:不会就问“我爹”
      • 原型编程的四大铁律(门规)
        • 所有数据都是对象
        • 想要新对象?别 new 类了,找个原型克隆一份!
        • 对象会记得它的“亲爹”是谁(原型)
        • 如果对象不会干某件事,它会把任务交给它的“原型爸爸”
    • JavaScript中的原型继承
      • 1️⃣ 所有的数据都是对象(或接近)
      • 2️⃣ 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它
      • 3️⃣ 对象会记住它的原型
      • 4️⃣ 如果对象无法响应某个请求,它会把这个请求委托给它的构造器的原型
    • 结语:

前言引入原型模式

本文的内容深受《JavaScript设计模式》一书的启发,特别是关于原型模式的讨论,该书深入浅出地介绍了这一重要的设计模式及其在JavaScript语言中的实现。原型模式不仅是众多设计模式中的一员,它更是构建JavaScript这门语言基础的核心之一。通过这本书,我们得以从更加简单的Io语言入手,逐步理解原型模式的概念,并学习如何在JavaScript中应用这一模式来创建强大而灵活的对象系统。
加之在面试过程中,对原型,原型链,圆形模式都很模糊,对《JavaScript设计模式》书中的原型模式进行深入反复学习将定义及理论理变为自己的语言重新组织输出。

头脑风暴

想象一下,你是一个程序员界的“Ctrl+C / Ctrl+V”大师。你不想每次都重新写代码,也不想手动配置一堆参数。你只想——一键克隆,天下我有!这,就是我们今天要说的主角:原型模式(Prototype Pattern)。

它不只是设计模式,它是一种编程哲学!
原型模式不仅仅是一个设计模式,它还是一个“编程泛型”级别的存在。你可以把它理解为:

“别跟我说什么类、继承、new 对象那一套,给我一个样板,我能克隆出一整个世界。”

从设计模式的角度来看,原型模式的核心思想是:与其造个类慢慢 new,不如找个现成的,咔嚓一下,直接复制一份!

传统方式 vs 原型模式

通常我们要创建一个对象,得先定义一个类,然后 new出来一个实例。比如:

let plane = new FighterPlane("红色", 100, "高级炮弹", 50);

这看起来很标准,但问题是:如果你想造一个跟这个飞机一模一样的分身呢?血量、武器、防御值、皮肤颜色……都得一个个手动传进去?那不是要命吗?你是写代码的,又不是在填表格!这时候,原型模式就闪亮登场了!原型模式是怎么干的?
原型模式说:

“嘿,别整这些麻烦事了。你不是已经有一个完美的飞机了吗?拿它当模板,克隆一个不就完了?”

于是你就调用了一个方法,比如:

let clonePlane = originalPlane.clone();

一句话搞定,啥都不用管。原飞机有什么属性,新飞机就自动拥有,连它的“坏脾气”都一起复制过去了!

实战案例:飞机大战中的分身术

假设你在开发一款网页游戏《飞机大战》,某个 boss 飞机突然大喊一声:“我要分身!”,你是不是得手忙脚乱地记下它当前的血量、攻击力、装备等级、飞行姿势……然后再 new 出一个一样的?不用了!现在只要一句:

let 分身 = 真身.clone();

克隆出来的分身不仅长得像,连战斗状态都同步了。真·完美复制!如果使用原型模式,我们只需要调用负责克隆的方法,便能完成同样的功能。

原型模式实现的关键秘密

通过上面讲解你还以为程序员只会 new 对象?不不不,我们还有更高级的操作——复制粘贴对象!
而实现这个魔法的关键,就是看语言有没有提供一个叫 .clone() 的方法。可惜的是,JavaScript 并没有原生的 .clone() 方法(别哭别沮丧,JS本来就不是那种贴心暖男型又或者贴心邻家大姐姐语言),但它给了我们另一个工具箱里的神器:Object.create(),这玩意儿就像是 JavaScript 界的“克隆羊多利”,只要你给它一个“母体对象”,它就能给你造出一个一模一样的副本!

实战演练:造一架能分身的飞机

让我们来看一段代码,看看怎么用 Object.create() 把飞机克隆出来!

	var Plane = function() { this.blood = 100; this.attackLevel = 1; this.defenseLevel = 1; }; var plane = new Plane(); plane.blood = 500; plane.attackLevel = 10; plane.defenseLevel = 7;

这段代码干了啥?你可以理解为:我们先 new 出了一个基础版小破飞机,然后给它加了个 buff,血量 +400,攻击力 +9,防御力也猛涨。现在它已经是一架“战神级飞机”了!那问题来了:你想再搞一架一模一样的飞机怎么办?难道要重新 new,再一个个属性设置一遍?太麻烦了!这时候,就该请出我们的主角登场了:💥 克隆大法好!

var clonePlane = Object.create(plane);

一句话,搞定克隆!就像你拿着这架飞机去复印店说:“老板,来一份复印件,不要改样式,我要原样再来一份。”于是你就得到了一架新的飞机,连它的“战斗状态”都一毛一样:

console.log(clonePlane); // 输出:Object {blood: 500, attackLevel: 10, defenseLevel: 7}

但是捏,老旧浏览器怎么办?有困难就解决困难!发动手动缝合克隆术!但总有那么几个“古董级浏览器”,比如IE8及以下,它们一脸懵逼地说:“什么?Object.create 是个啥?”,那怎么办?别慌,我们可以自己写一个“土法”克隆术:

Object.create = Object.create || function(obj) {var F = function() {};F.prototype = obj;return new F();
}

这相当于你在对浏览器说:

“既然你不支持克隆技术,那我就自己搭个克隆实验室!用 prototype 搞点遗传工程,照样能造出一模一样的飞机!”

虽然看起来有点土,但效果一样顶呱呱!

克隆是创建对象的手段

通过上面飞机分身复制术,你以为原型模式只是个“复制粘贴工具人”?错!它真正的身份是——宇宙造物主级别的对象工厂!别看它表面是在“克隆”,其实它心里想的是:

“我不只是在复制一个对象,我是在帮你创建一个新的世界。”

🤔 克隆只是手段,造对象才是目的!就像你去餐厅点了一份红烧肉,厨师说:“哎呀今天没肉了,我就给你端了一盘一模一样的昨天剩菜。”虽然看起来一样,但本质不一样!

原型模式也是一样:

表面上看:它在“复制”一个对象。
实际上:它是在用“复制”这种方式,来创建一个新对象。

换句话说:克隆只是过程,不是目的。就像洗澡是为了干净,不是为了泡水。

💼 举个 Java 程序员的苦逼例子
Java 这种“类型洁癖症晚期”语言中,写代码就像是在做数学证明题:类型必须严格匹配,创建对象要 new 某个具体的类名,如果你想换实现?不好意思,得改代码、加依赖、重新编译……,这时候设计模式就站出来说话了:

“兄弟,咱们得解耦啊!”

“不能直接 new 对象,得搞个工厂出来!”

于是就有了:

工厂方法模式(Factory Method)
抽象工厂模式(Abstract Factory)

结果呢?本来只是想造一架飞机,现在还得先建个“飞机制造工厂公司集团有限公司”。更惨的是,每个飞机型号都得配一个对应的工厂……这代码量,简直爆炸!

原型模式:轻装上阵的造物术

这时候原型模式闪亮登场了,它甩掉所有繁琐的类和工厂,只说一句话:

“别整那些虚的,给我一个样板,我能造出一个一模一样的。”

这就像一个小女孩指着商店里的玩具飞机说:

“我要这个!”

而不是说:

“我要一个飞行器,材质塑料,动力系统为螺旋桨驱动,翼展15cm……”

她不懂那么多术语,但她知道:这个就是我要的对象!所以,原型模式的本质是:

✅ 不需要知道具体类名
✅ 不需要 new 出来一堆耦合
✅ 只要有一个对象,就能作为模板,轻松造出新的对象!

当然啦,在 JavaScript 的世界里,这一切变得更加丝滑。因为 JS 本身就是基于原型的语言,它不靠“类”来创建对象,而是靠“原型链”来继承属性。你可以理解为:JS 的对象系统,就是用原型模式搭起来的。所以从这个角度讲,在 JavaScript 中使用原型模式,有点像是:

“给猫装胡须,给鱼装鳃,给程序员发咖啡。”

已经自带技能了好吗!不过,如果你真要用原型模式来做业务逻辑上的对象创建,也不是不行。比如:

let plane = { blood: 500,attackLevel: 10,defenseLevel: 7,fire: function() {console.log("发射导弹!");}
};
let clonePlane = Object.create(plane);
clonePlane.name = "分身一号";

你看,不需要 new Plane(),也不需要写构造函数,只要有个原型对象,就可以直接克隆出一个新对象。是不是很像魔法?是不是比写一堆 classfactory 干净多了?

📚 总结一下:原型模式到底图啥?

传统模式原型模式
new XXX(),依赖具体类克隆已有对象,不关心类名
需要工厂类支持一行代码搞定
容易耦合更加灵活

原型编程范型的一些规则

原型编程的四大门规:不会就问“我爹”

JavaScript 的江湖里,有个神秘的门派叫——原型宗(Prototype Sect)。这个门派不讲“类”,不搞“继承”,他们只信奉一个真理:

“不会?没问题,去问你爹。”

这,就是我们今天要说的——原型编程范型的基本规则。

原型编程的四大铁律(门规)

所有数据都是对象

没错,在这里没有“原始类型”这种说法,哪怕是数字、字符串,都被当作“对象小弟”来看待。你可以理解为:在原型宗的地盘上,连数字都想当大哥。

let x = 5;
x.isAlsoAnObject = true; // 虽然 JS 会临时包装成对象,但意思到了就行 😄
想要新对象?别 new 类了,找个原型克隆一份!

别人创建对象靠 new Plane(),原型宗靠“复印机”。只要找到一个现成的对象作为“模板”,轻轻一按:
“Ctrl+CCtrl+V,一个一模一样的飞机就出来了。”

let plane = { blood: 500, attackLevel: 10 };
let clonePlane = Object.create(plane);

一句话搞定,啥都不用写!

对象会记得它的“亲爹”是谁(原型)

每个对象心里都清楚,自己是从哪个原型克隆来的。就像孩子知道自己老爸是谁一样,JS 中的对象也有一条“血缘链”——原型链(Prototype Chain)你虽然没有显式地声明继承关系,但它默默地记住了它的“原型爸爸”。

如果对象不会干某件事,它会把任务交给它的“原型爸爸”

这是原型宗最核心的一句话:

“我不行?没关系,我爹行!”

比如你想让一个对象执行某个方法,它自己没这个技能,它就会顺着原型链往上找:

自己有没有?没有。
爸爸有没有?有!借来用!

这就叫做:委托机制(Delegation

let dog = {bark: function() {console.log("汪汪汪!");}
};
let buddy = Object.create(dog);
buddy.bark(); // 输出:"汪汪汪!",虽然 buddy 自己没定义这个方法

🧾 总结一下:原型宗四大门规

规则编号内容描述解释
Rule 1所有数据都是对象数字也会装逼说自己是对象
Rule 2得到对象靠克隆原型,不是靠 new 类 不写构造函数只管复制粘贴
Rule 3对象知道自己的原型是谁孩子知道自己老爸是谁
Rule 4请求失败时,委托给原型处理 自己不会?去找你爹!

JavaScript中的原型继承

JavaScript 的世界里,没有 Java 那种“类”的概念,它走的是另一条路——原型编程(Prototype-based Programming)。这就像:别人靠“父母”生孩子,JS 靠“克隆”造对象。现在我们就来看看 JavaScript 是如何通过原型链实现对象之间的继承关系的。

1️⃣ 所有的数据都是对象(或接近)

JavaScript 在设计之初模仿了 Java,引入了两套类型机制:基本类型对象类型。基本类型包括 undefinednumberbooleanstringfunctionobject。但说实话,这种设计有点迷糊。按照 JS 设计者的初衷,除了 undefined 外,其他一切都是对象。为了让 numberbooleanstring 这些基本类型也能像对象一样被处理,JS 引入了“包装类”。虽然不能说所有数据都是对象,但可以说绝大部分数据是对象。而且,在 JavaScript 中有一个根对象存在,那就是 Object.prototype。它是所有对象的老祖宗,所有对象追根溯源都来源于这个根对象。

比如下面的例子:

var obj1 = new Object(); 
var obj/XMLSchema = {};
console.log(Object.getPrototypeOf(obj1) === Object.prototype); // 输出:true 
console.log(Object.getPrototypeOf(obj2) === Object.prototype); // 输出:true 

这就像是所有的对象都认同一个老祖宗——Object.prototype

2️⃣ 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它

JavaScript 中,我们并不需要关心克隆一个对象的这些细节,因为这是引擎内部的事儿。当我们调用 new Object() 或者 {}来创建对象时,引擎会从 Object.prototype 上面克隆出一个新的对象。再来看个例子:

	function Person(name) { this.name = name; }Person.prototype.getName = function() { return this.name; };var a = new Person('sven');console.log(a.name); // 输出:sven console.log(a.getName()); // 输出:sven console.log(Object.getPrototypeOf(a) === Person.prototype); // 输出:true 

x
虽然我们用了 new 关键字,但其实并没有真正意义上的“类”,Person 只是个构造器。使用 new 创建对象的过程,实际上也只是先克隆 Object.prototype 对象,再进行一些额外操作。

3️⃣ 对象会记住它的原型

每个对象都记得自己的“亲爹”是谁(即它的原型)。为了实现这一点,JavaScript 给对象提供了一个隐藏属性——__proto__。这个属性指向对象的构造器的原型对象 {Constructor}.prototype

例如:

var a = new Object();
console.log(a.__proto__ === Object.prototype); // 输出:true 

这就像是对象之间有一条看不见的线,把它们串在一起。当我们用new创建对象时,需要手动设置 obj.__proto__ = Constructor.prototype,这样才能让对象正确地找到它的“亲爹”。

4️⃣ 如果对象无法响应某个请求,它会把这个请求委托给它的构造器的原型

这条规则就是原型继承的精髓所在。当一个对象无法响应某个请求时,它会顺着原型链把请求传递下去,直到遇到一个能处理该请求的对象为止。

举个例子:

var obj = { name: 'sven' }; 
var A = function(){}; 
A.prototype = obj; 
var a = new A(); 
console.log(a.name); // 输出:sven 

在这个过程中,如果对象 a 没有找到 name 属性,它就会沿着原型链向上查找,直到在 obj 中找到了name 属性,并返回其值。再看一个稍微复杂一点的例子:

var A = function(){}; 
A.prototype = { name: 'sven' }; 
var B = function(){}; 
B.prototype = new A(); 
var b = new B(); 
console.log(b.name); // 输出:sven 

当尝试访问 bname 属性时,如果 b 自己没有这个属性,它会沿着原型链向上查找,直到在 A.prototype 中找到 name 属性,并返回其值。

再看这段代码执行的时候,引擎做了什么事情:

  • 首先,尝试遍历对象 b 中的所有属性,但没有找到 name 这个属性。
  • 查找 name 属性的请求被委托给对象 b 的构造器的原型,它被 b.__proto__ 记录着并且指向
    B.prototype,而 B.prototype 被设置为一个通过 new A()创建出来的对象。
  • 在该对象中依然没有找到 name 属性,于是请求被继续委托给这个对象构造器的原型A.prototype。
  • 在 A.prototype 中找到了 name 属性,并返回它的值。

        和把 B.prototype 直接指向一个字面量对象相比,通过 B.prototype = new A()形成的原型链比之前多了一层。但二者之间没有本质上的区别,都是将对象构造器的原型指向另外一个对象,继承总是发生在对象和对象之间。
        最后还要留意一点,原型链并不是无限长的。现在我们尝试访问对象 aaddress 属性。而对象 b 和它构造器的原型上都没有 address 属性,那么这个请求会被最终传递到哪里呢?
实际上,当请求达到 A.prototype,并且在 A.prototype 中也没有找到 address 属性的时候,请求会被传递给 A.prototype 的构造器原型 Object.prototype,显然 Object.prototype 中也没有address 属性,但 Object.prototype 的原型是 null,说明这时候原型链的后面已经没有别的节点了。所以该次请求就到此打住,a.address 返回 undefined

a.address // 输出:undefined

🧩 总结一下:原型继承的核心思想

规则编号内容描述理解
Rule 1所有数据都是对象(或接近)老祖宗是 Object.prototype
Rule 2得到对象靠克隆原型,不是靠 new 类new 类 不写构造函数,只管复制粘贴
Rule 3对象知道自己的原型是谁孩子知道自己老爸是谁
Rule 4请求失败时,委托给原型处理自己不会?去找你爹

💬 最后一句灵魂总结:
在 JavaScript 的世界里,你不靠“类”吃饭,你靠“原型”混江湖。遇事不懂?先问问你爹再说!

结语:

本文的内容深受《JavaScript设计模式》一书的启发,特别是关于原型模式的讨论,该书深入浅出地介绍了这一重要的设计模式及其在JavaScript语言中的实现。原型模式不仅是众多设计模式中的一员,它更是构建JavaScript这门语言基础的核心之一。通过这本书,我们得以从更加简单的Io语言入手,逐步理解原型模式的概念,并学习如何在JavaScript中应用这一模式来创建强大而灵活的对象系统。
在此,我对《JavaScript设计模式》的作者表示深深的感谢和敬意。是你细致入微的讲解让复杂的设计模式变得易于理解,也为像我这样的开发者提供了宝贵的指导和灵感。如果你希望深入了解JavaScript中的设计模式及其背后的原理,《JavaScript设计模式》绝对是一本不容错过的好书!

致敬—— 《JavaScript设计模式》· 曾探

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/pingmian/82732.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据库】概述(纯理论)

数据库系统引论 数据管理系统的发展 数据管理:对数据分类、组织、编码、存储、检索、维护 发展:人工管理、文件系统、数据库系统 40-50年代 人工管理 数据不保存,没有专门软件管理数据,应用程序完全依赖于数据,数据…

语音合成之十七 语音合成(TTS)中文自然度:问题、成因、解决方案

语音合成(TTS)中文自然度:问题、成因、解决方案 中文TTS系统基本架构中文TTS常见问题深度剖析与解决方案音色跳变成因分析解决方案 声调与重读错误成因分析业界解决方案 漏读与断句错误成因分析业界解决方案 在跨语言TTS系统比较中&#xff0…

我在 Linux 进程管理中踩过的坑:僵尸、瞬时与不可中断进程实战实录

作为运维老鸟,我曾在 Linux 进程管理上栽过不少跟头。记得第一次遇到满屏僵尸进程时,服务器直接卡到连 SSH 都登不上,看着ps命令里一排排刺眼的Z状态进程,手心直冒冷汗。后来又碰到过瞬时进程搞崩日志系统,明明监控显示…

【设计模式】简单工厂模式,工厂模式,抽象工厂模式,单例,代理,go案例区分总结

工厂模式三种类型: 一、简单工厂模式(Simple Factory) 定义: 用一个工厂类,根据传入的参数决定创建哪一种具体产品类实例。 面试说法: 由一个统一的工厂创建所有对象,增加新产品时需要修改工…

某标杆房企BI平台2.0升级实践

当房地产行业从“规模竞赛”转向“精益运营”,数字化转型成为破局关键。某千亿房企携手亿信华辰,以“用数据重构业务价值链”为目标,历经6个月完成BI平台战略性升级。在这场从“数据可视化”到“决策智能化”的跃迁中,亿信华辰ABI…

Lua 脚本在 Redis 中的运用-24 (使用 Lua 脚本实现原子计数器)

实践练习:使用 Lua 脚本实现原子计数器 实现原子计数器是许多应用程序中的常见需求,例如跟踪网站访问量、限制 API 请求或管理库存。虽然 Redis 提供了 INCR 命令用于递增整数,但在复杂场景或与其他操作结合时直接使用它可能并不足够。本课程探讨了如何在 Redis 中利用 Lua…

Rust 学习笔记:使用迭代器改进 minigrep

Rust 学习笔记:使用迭代器改进 minigrep Rust 学习笔记:使用迭代器改进 minigrep不使用 clone,而使用迭代器使用迭代器适配器使代码更清晰在循环或迭代器之间进行选择 Rust 学习笔记:使用迭代器改进 minigrep 前情提要&#xff1…

el-table配置表头固定而且高度变化

根据官网提示只要在 el-table 元素中定义了 height 属性,即可实现固定表头的表格,而不需要额外的代码。 如果你想既要固定表头,又要下方表格高度自适应,可以设置为 height"100%" : 然后外层设置scroll:

弱光环境下如何手持相机拍摄静物:摄影曝光之等效曝光认知

写在前面 博文内容为一次博物馆静物拍摄笔记的简单总结内容涉及:弱光环境拍摄静物如何选择,以及等效曝光的认知理解不足小伙伴帮忙指正 😃,生活加油 我看远山,远山悲悯 持续分享技术干货,感兴趣小伙伴可以关注下 _ 采…

ARM笔记-ARM伪指令及编程基础

第四章 ARM伪指令及编程基础 4.1 伪指令概述 4.1.1 伪指令定义 人们设计了一些专门用于指导汇编器进行汇编工作的指令,由于这些指令不形成机器码指令,它们只是在汇编器进行汇编工作的过程中起作用,所以被叫做伪指令。 4.1.2 伪指令特征 …

智能手表怎么申请欧盟EN 18031认证

智能手表申请欧盟 EN 18031 认证(针对消费类物联网设备的网络安全标准)的流程与智能门锁类似,但需结合手表的功能特性(如数据交互、定位、支付等)调整合规重点。以下是具体流程和关键要点: 一、标准适配与…

算法-全排列

1、全排列函数的使用 举例&#xff1a;{1,2,3}的全排列 #include<iostream> #include<bits/stdc.h> using namespace std; typedef long long ll; int main(){ll a[3] {1, 2, 3};do{for (ll i 0; i < 3;i){cout << a[i] << " ";}cout…

面试加分秘籍:校招数据倾斜场景下的SQL优化方案

校招面试经常会问大家有没有过调优的经验&#xff0c;相信大家的回答基本都是往数据倾斜和小文件问题这两方面回答&#xff0c;对于数据倾斜相信大部分同学对热key打散或null值引发的倾斜已经非常熟悉&#xff0c;但这些内容面试官也是听腻了&#xff0c;希望大家在面试时候讲一…

Elasticsearch索引机制与Lucene段合并策略深度解析

引言 在现代分布式搜索引擎Elasticsearch中&#xff0c;文档的索引、更新和删除操作不仅是用户交互的核心入口&#xff0c;更是底层存储架构设计的关键挑战。本文围绕以下核心链路展开&#xff1a; 文档生命周期管理&#xff1a;从客户端请求路由到分片定位&#xff0c;从内存…

git提交更改

第一步&#xff1a;添加改动 git add . 第二步&#xff1a;提交改动 git commit -m “替换了 SerialPort 库文件” 第三步&#xff1a;推送到远程 git push 为什么git 的UI界面做的远不如SVN

WPF的基础控件:布局控件(StackPanel DockPanel)

布局控件&#xff08;StackPanel & DockPanel&#xff09; 1 StackPanel的Orientation属性2 DockPanel的LastChildFill3 嵌套布局示例4 性能优化建议5 常见问题排查 在WPF开发中&#xff0c;布局控件是构建用户界面的基石。StackPanel和DockPanel作为两种最基础的布局容器&…

互联网大厂Java求职面试:AI大模型推理服务性能优化与向量数据库分布式检索

互联网大厂Java求职面试&#xff1a;AI大模型推理服务性能优化与向量数据库分布式检索 面试现场&#xff1a;技术总监的连环追问 技术总监&#xff1a;&#xff08;翻看着简历&#xff09;郑薪苦&#xff0c;你在上一家公司参与过LLM推理服务的性能优化项目&#xff1f;说说你…

如何解决网站服务器的异常问题?

当网站服务器出现异常情况&#xff0c;导致用户无法正常访问网页信息的时候&#xff0c;该如何解决这一问题呢&#xff1f;小编下面就带领大家共同探讨一下这一问题。 企业在面对网站服务器异常时&#xff0c;首先要对服务器硬件设备进行详细的检查&#xff0c;可以使用硬盘检测…

Day 35

模型可视化与推理 知识点回顾&#xff1a; 三种不同的模型可视化方法&#xff1a;推荐torchinfo打印summary权重分布可视化 进度条功能&#xff1a;手动和自动写法&#xff0c;让打印结果更加美观 推理的写法&#xff1a;评估模式 模型结构可视化 理解一个深度学习网络最重要的…

[yolov11改进系列]基于yolov11引入自注意力与卷积混合模块ACmix提高FPS+检测效率python源码+训练源码

[ACmix的框架原理] 1.1 ACMix的基本原理 ACmix是一种混合模型&#xff0c;结合了自注意力机制和卷积运算的优势。它的核心思想是&#xff0c;传统卷积操作和自注意力模块的大部分计算都可以通过1x1的卷积来实现。ACmix首先使用1x1卷积对输入特征图进行投影&#xff0c;生成一组…