【设计模式】设计模式介绍
一、设计模式概述
设计模式分很多种,每种一般都用于解决某个软件开发过程中的问题。许多人认为设 计模式有23种,其实,对于这个数字也没必要那么教条,当然还有更多的设计模式种类,只 不过是这23种比较经典而已。甚至可以说,如果你有很丰富的程序设计经验,那么你发明 自己的设计模式也没问题。
模式,是指事物的标准样式或者针对特定问题的可重用解决方案。换句话说,遇到这类 问题,用这种解决方法;遇到那类问题,用那种解决方法;遇到不同的问题,用不同的解决 方法——这就是模式。
再回到“设计模式”这个词上来,这个词的英文是Design Pattern,以下几种对“设计模 式”的解释都可以
- 设计模式,是一套被反复使用的代码设计经验的总结,是经过提炼的出色的设计 方法。
- 设计模式,是程序员在长期的开发实践中总结出的一套提高开发效率的编程方法。
- · 设计模式,代表了一些解决常见问题的通用做法,体现着人们尝试解决某些问题时
的智慧。所以,它是一种强大的管理复杂度的工具。 · 设计模式,是在特定问题发生时的可重用解决方案。 - 一个设计模式用来描述几个模块或类对象之间关系、职责,以及它们之间如何进行 分工与合作。 一个甚至几个设计模式共同配合来解决软件设计中面对的实际问题。
- 设计模式在比编程语言惯用手法更高的层面来描述解决特定类型问题的途径。
- 设计模式用来描述在软件系统中如何通过管理代码的相互依赖性来管理复杂性。
使用设计模式的主要目的是在设计大型项目时,保证所设计的模块之间的代码灵活性 和可复用性,但是毫无疑问,这两个特性都以增加复杂性作为代价。
- 灵活性(可扩展性/低耦合性)
- 谈到灵活性这件事,可以想象一下3D 网络游戏里面的人物,刚出现在游戏世界中的时 候,人物形象可能是光着膀子;
- 当人物达到5级的时候,玩家给人物买了一件布衣,穿上之 后,人物的形象发生了改变;当人物达到10级的时候,玩家给人物买了一件皮衣,穿上之 后,人物的形象又发生了改变,这就是人物形象灵活性的体现。
- 在制作游戏中人物的时候,先做一个裸体的人物模型,衣服也单独做成模型,做一件 布衣模型,做一件皮衣模型。
- 当人物穿布衣的时候,通过编写程序,把布衣模型贴到人物模型上。当人物改穿皮 衣的时候,依旧通过编写程序,把布衣模型从人物模型上摘下来,把皮衣模型贴到人 物模型上去。从而实现了只要变换衣服模型就可以改变整个人物外观的需求。
- 反之,如果把人物模型和衣服模型做到一起,成为一个整体的话,那就面临着人物+布 衣要做一个模型,人物+皮衣要做一个模型……这不但劳民伤财,而且人物模型载入(显示 到屏幕)的时间一般会比较长,可能造成游戏卡顿,影响玩家体验。所以,除非有十分必要的 理由,否则应该尽可能选择这种具有灵活性的解决方案。
总结一下,所谓灵活性可以理解为两点:
- 修改现有的某部分内容不会影响其他部分的内容(影响面尽可能窄或者说尽量将修 改的代码集中在一起,不希望大范围修改代码)。
- 增加新内容的时候尽量少甚至不需要改动系统现有的内容。
- 可复用性
刚才谈到了《设计模式——可复用面向对象软件的基础》一书,从书名中,可以提取出来 两个非常重要的词:可复用和面向对象。
- 可复用:可以重复使用,可以到处用(可以被很多地方调用)。
- 面向对象有三大特性———封装性、继承性、多态性。其中的多态性对于学好设计模式非 常重要,读者一定要好好理解,可以仔细阅读《C++ 新经典:对象模型》 ——其中对多态性有 相当深入的解释。
C++支持很多种风格的程序设计方法,或者说C++支持很多种编程模型:
- (1)面向过程;
- (2)基于对象;
- (3)面向对象(基于对象的编程模型融入继承性和多态性后形成的);
- (4)泛型编程等。通常情况下,设计模式是指面向对象这种编程模型下的设计模式,组合使用各种设计模式来进行面向对象程序设计。但是,设计模式并不等价于面向对象的设 计模式,也就是说,脱离面向对象这个概念,设计模式的概念也可以单独存在。这里不多谈, 读者在日后工作中遇到类似的问题时可以再进行深入的研究。
灵活性和可复用性两者是相辅相成的,没必要分开理解,可复用也意味着很灵活,灵活 性也意味着可复用。设计模式也被称为微架构(Micro-Architecture), 各种设计模式的组合 运用可以生成各种新的架构。
1.1 设计模式中的抽象思维
下面先解释一下“耦合”和“解耦合”这两个概念。
- 耦合:两个模块相互依赖,修改其中的一个模块,则另外一个也要修改,这两者之间 存在的互相影响关系就叫作两个模块之间存在耦合关系。
- 解耦合:通过修改程序代码,切断两个模块之间的依赖关系,使得对于任意一个模 块的更改都不会影响另外一个模块,这就叫两个模块之间已经解耦合了。
回归到“抽象思维”这个话题中来——抽象思维在设计模式中的运用非常重要,抽象思 维强调对象的本质属性,主要应用于一些软件设计中的解耦合过程。
1. 抽象思维的概念
什么叫抽象思维呢?对于一个事物,所谓的抽象思维,是指能从这个事物中抽取出或者 说提炼出一些本质的、共性的内容,把这些共性的内容组合到一起(封装)。
例如狗、猫、猪,针对这3种动物,看一看怎样把它们的一些共性的内容提取出来做个抽 象(抽象成一个基类或者说基类本身就是一种抽象)。
- (1)它们都是动物,它们都要吃,都要喝,这是它们的共性,所以可以抽象出一个叫作动 物的类,吃、喝都可以作为动物这个类成员函数。
class Animal
{
public:void eat(){}void drink(){}
};
- (2)当然,狗、猫、猪还有各自不同的特点,例如狗可以看家,猫可以抓老鼠,猪可以养肥 吃肉,等等,不过这些内容不在抽象思维这个话题中,故不多探讨。
上面举出的这个抽象思维的小范例比较简单和显而易见,所以比较好理解,但是在一个 大型的复杂项目中,要利用抽象思维把一些事务的共性提取出来,并不是一件容易的事。从 编程思维的角度来思考,下面两种解决问题复杂性的方法可以借鉴。 - 分解法:把一个复杂的事物分解成若干比较简单的事物。因为人们能够更轻松地 理解多个简单的事物而不是一个复杂的事物。
- 抽象法:从每个简单的事物中,抽象出本质的内容并封装起来。抽象思维的能力因人而异,跟传统教育有关系,跟后天的培养也有关系,总之是一个复 杂的事情。
毫无疑问,设计模式是很依赖抽象思维的——尽量尝试把一个事物的本质内容抽取出 来。所以,学习设计模式的过程,也是一个不断提高自己抽象思维能力的过程。
- 抽象思维的目的
那么,为什么要利用抽象思维把事务中一些本质、共性的内容提取出来?这样做有什么 好处呢?
假设,读者是一个农场主,农场里目前有3种动物,狗、猫、猪,现在要对这3种动物进行 管理。从写程序的角度来讲,可以对这3种动物分别创建类:狗、猫、猪。对于这3种动物 类,每个类都要实现一些成员函数(方法),例如狗,要实现的成员函数有———吃、喝、看家; 猫,要实现的成员函数有——吃、喝、捉老鼠;猪,要实现的成员函数有——吃、喝、被屠宰。
除了对这3种动物分别创建3个类之外,是否还有更好的程序写法呢?
仔细想想,不难 发现,在狗、猫、猪这3种动物的类中,都有吃、喝这两个成员函数。但是,每个类又分别有不 同的成员函数,例如狗的专有成员函数是“看家”,而猫的专有成员函数是“捉老鼠”,猪的专 有成员函数是“被屠宰”。有了这些想法,就可以重新设计这些类,设计的原则就是减少代码 的重复性,方便代码的扩展( 例如日后可以灵活地加入新的动物品种)。
- 吃、喝这两个成员函数既然每种动物都有,那么可以专门创建一个动物类(Animal),
把吃、喝这两个成员函数放进去。这就不用在狗、猫、猪类里面都写吃、喝这两个成 员函数,从而减少了代码的重复性。这里,就抽象出了动物类,做抽象的原则是把比 较稳定的、不怎么变化的内容作为一个模块,单独定义出来。 - 分别定义狗、猫、猪这3个类,将这3个类定义为继承自动物类,那么这3个子类就 自动拥有了“吃""喝”这两个成员函数。
- 在父类(动物类)中定义一个“用途”成员函数,这个成员函数应该设计为一个虚函 数 。之后,在狗、猫、猪这3个子类中分别实现“用途”成员函数,例如,狗的用途是看 家,猫的用途是捉老鼠,猪的用途是被屠宰,等等。换句话说,不同种类的动物,它们 的用途是不同的、是变化的,所以要把变化的这部分内容放到每个子类中去实现。
请读者想一想:这种设计方式是不是更好?是否起到了减少代码重复性,方便代码扩 展性的目的呢?
- 抽象思维的检验
对于一个项目,把哪些内容抽象出来封装成一个类,是一件很主观的事情,没有统一的 设计标准,不同的人有不同的做法。那么怎么检验某种抽象是否合适?
-
面对一个项目时,如果项目的某些需求发生更改(实际上软件领域的需求变更是经 常发生的),不更改现有的代码,通过增加新代码应对需求变更。例如,农场里增加 一种新动物——公鸡,公鸡的主要用途是报晓,这个时候,可以直接创建一个公鸡 类,同样继承自动物类,然后也在其中实现“用途”成员函数,在这个成员函数中实现 报晓这个功能。
这里进一步提一下继承,继承是面向对象的特性之一,用于表达类与类之间的父子 关系,这种父子关系一般用于表达两种意思: -
(1)抽象机制———就是上面谈到的,抽取出本质的、共性的内容放到基类中;
-
(2)可重用机制——基类中的一些内容,直接拿过来使用。
当一个类中内容太多时,就要考虑是否可以将该类进一步拆分。尤其注意不要把一 些毫不相关的内容都写到一个类中。面向对象程序设计有一个设计原则叫“单一职 责原则”,意思就是说一个类只干好一个事情,承担好一种责任,不然就会牵扯太多, 不管哪块需求变化了都需要修改这个类,那就麻烦了。这跟人一样,你又当语文课 代表,又当数学课代表,还兼任班长,那就麻烦了,一会儿班主任找你,一会儿语文老 师找你,一会儿数学老师找你,你就忙不过来了。
1.3 学习设计模式普遍存在的问题
设计模式是一把双刃剑,若用得好,能提高系统的灵活性、可复用性等,但乱用或错用也 会造成系统适用性的降低。很多读者都学习过设计模式,学习之后,普遍存在一些共性 问 题 。
-
听得懂但不会用
讲解的内容能听懂,能理解,但不知道在具体工作中如何应用或者说无法得心应手地使 用。换句话说,就是知道代码是这样写的,但不知道为什么要这样写代码。
设计模式相关知识的产生,是因为人们进行项目设计时,随着代码规模的逐步增大,逐 步遇到代码灵活性不够、牵一发而动全身的窘况,此时的代码变得越来越难以修改和维护, 为了应对这个问题,人们不得不采取一些必要的手段对代码进行重新设计,提炼其中的设计 规律,最终总结成各种设计模式。
学习设计模式的有效之法是忘记设计模式,先面对具体要解决的问题,只有经历了“遇 到难题 →用了一个很笨重的方法解决,效果很不理想 →采用设计模式解决,效果比较理想” 的步骤,才能对设计模式印象深刻并做到学以致用。 -
学完了之后到处滥用
设计模式是用来解决大型项目设计时遇到的各种代码问题的,换句话说,就是先有问 题,再有设计模式。
但很多程序开发者往往本末倒置, 一个本来没有多少行代码的小项目在编写代码的时 候非要往设计模式上套(上来就用设计模式),非要让代码中充斥各种设计模式,似乎只有这 样才能体现出程序设计者的高、大、上,这是非常错误的做法,也容易导致出现一些很差劲的 设计(差劲的设计是指这种设计的用途非常有限,却因为引入过多的类而大大增加了他人理 解代码的难度和学习时间,把简单问题复杂化了)。当然,这并不是说小项目就不需要设计, 小项目也同样需要先做设计,再动手编码。
设计项目的时候需要遵守几个原则:
- 不要过度设计,把未来十年八年的事都考虑进来,这没必要,能够支撑未来1~2年 的扩展就行了,其实对于一个小项目如果一开始就引入设计模式,往往会过度设计。
- 设计是一件很主观的事,也不是一步到位的事,可能需要不断地调整和修改。因为 随着个人的成长,想法、见识会不断提高,设计也就自然会不断改进(重构)。
- 不要为了用模式而用模式,使用模式之前,必须要考虑该模式是否适合,往往代码的 实用性和易读性更重要。
3. 设计模式无用论
一般来讲,这种观点属于无稽之谈。
在实际工作中,绝大多数的开发者面临的都是几千到几万行代码的项目。这个时候其 实只要代码写得过得去,总是可以把项目完成,确实也不太需要用到设计模式。但是, 一旦 代码达到十几万行甚至二十万行,读者千万不要简单地以为无非就是代码多了10倍而已, 绝不是这样简单计算的。编写2万行代码,确实用不上设计模式也能写得很愉快,但是,编 写20万行代码,如果不用设计模式,到了开发的后期开发者可能会疯掉,那种难以扩展、难 以维护的感觉,会非常让人纠结和痛苦。换句话说,驾驭几十万行代码的项目,需要的是掌 握设计模式这种开发技术(开发技巧)。
其实,很多开发者在编写代码时总会在无意之间就使用到某种设计模式,只不过自己没 有意识到而已。
1.1.4 设计模式的缺点
灵活性和可复用性,显然是设计模式的两大核心优点,但是引入设计模式,也会让程序 员付出代价,对这种代价也应该有所了解。
- 增加程序书写的复杂性:遵从设计模式书写的程序代码往往与普通的程序代码不 太一样,但是经过一定的学习,程序员还是能够渐渐熟悉这种程序书写方式。
- 增加了学习和理解上的负担:为了代码编写的灵活性,在解决一个问题的时候,往 往要引入多个类(而以往可能只需要一个类就能解决问题),这些类之间配合起来实 现指定的功能,这无疑给代码的学习者和阅读者增加了理解负担。所以设计模式的 使用必须要小心谨慎,尽量不要引入不必要的复杂性,从管理的角度上有一句俗话 叫作“用户想要一杯茶,就不要为他创建一个能煮沸海洋的系统”。
- 设计模式的引入会在一定程度上降低程序的运行效率,这是显然的。因为一个功能 要几个类配合起来实现,显然会增加额外的调用类成员函数的时间成本(例如以往 调用一个成员函数实现,现在要调用5个成员函数来实现)。当然, 一般来讲,相比 于设计模式带来的好处,这种时间成本的付出是值得的(除非真正面临效率瓶颈问 题)。如果在一些资源贫瘠又极度注重效率的系统上,那么在开发的时候是否引入 设计模式,就是一个值得考虑的问题了。
1.1.5 设计模式在实际工作中的应用和学习方法
这个问题要分两方面看。
- 日常工作中的小项目
在日常的小项目开发中,用到设计模式知识的机会并不多。主要原因有如下几点:
- 所开发的项目规模偏小,可能只有几千行代码,当需求变动时,可以方便地修改 代 码 。
- 项目的逻辑功能比较单一,只用于解决眼下问题,不需要将编写的代码提供给他人 复 用 。
- 即便是这样的小项目,开发者可能也在无意中使用了一些设计模式,只不过开发者 没意识到使用的是哪种设计模式。
- 大型应用项目和框架类项目
一旦应用项目较大,例如达到5万行甚至10万行代码,向其中增加新的代码和新的功 能变得越发困难,项目变得越来越笨重,如果不精心设计项目的结构,就会导致出现大量的 冗余代码,灵活性尽失。
对于这种被诸多项目使用的框架类项目,就更需要具备极高的灵活性和可复用性,适应 各种不同的环境、不同的操作系统平台。 框架可以理解成多种设计模式的综合运用所生成 的半成品,开发人员需要向其中增加更多的实现代码以最终形成成品应用程序。
所以,在大型项目和框架类项目中,才是设计模式真正发挥重要作用的舞台。 那么,对于设计模式的学习和掌握,建议采用如下步骤和方法:
- (1)掌握设计模式的基本概念和该设计模式要解决的具体问题,这样当碰到类似问题 时,就能够快速识别并运用对应的设计模式。
- (2)动手实际编写相关的测试代码并进一步体验该模式的工作过程。这一步对深入扎 实地掌握该模式将起到不可替代的作用, 一定不要略过。
- (3)在编码过程中要不断思考和总结设计经验,对于设计不合理的部分及时调整和更改。
- (4)在实际项目中,细致大胆地采用设计模式进行实战,尤其注意采用多个设计模式解 决问题时模式之间的关联和配合,不要怕出错。其实,程序设计中的最好、最通用、最正确之 说都是相对的,没有绝对的。
二、大型项目的软件开发思想
- 基本思想
对于大型项目的开发工作,需要注意如下几点。
-
(1)前期做细致的需求分析以及架构设计是非常重要的,应该多花时间去撰写相关的 需求文档、规划设计文档,安排合理的进度,文档应该为未来的项目规模增长提供一定的伸 缩性。力求让项目有一个良好的开端,为程序员提供开发参照和指导,尽量减少后期调整和 改动的成本。
-
(2)对于设计的层次来讲,不要一上来就设计类,而应当先划分成各个模块(子系统)。 在对模块进行明确划分的前提下,再进行类的划分,确定好类的接口。有些模块只需要单独 一个类即可实现,而有些模块需要多个类之间协作才能实现。对于每个类的设计应该有清 晰的认识,包括为何进行这样的设计、设计的具体细节等内容。设计是一种迭代的过程,不 可能一蹴而就。
模块之间交互时要限制与当前模块交互的其他模块数量。错综复杂的交互会让设计显得特别凌乱。
- (3)大型项目往往最让人头疼的问题是可维护性和可扩展性,如果模块之间的耦合度特 别高(紧耦合),那么随着项目代码的增多,那种牵一发而动全身的功能扩展让程序开发人员如 入泥沼,极度无奈。所以,尽可能降低模块之间的耦合度(解耦),其实,从某种角度上来说,学 习设计模式的本质就是寻求模块之间的解耦,耦合度越低,就越容易专注解决一小块问题。
- 微服务架构设计模式与设计模式的区别
微服务这个概念,读者多多少少都听说过,也是在2010年之后开始逐渐流行起来。为什 么这个概念会流行起来呢?主要是因为互联网业务规模的不断变大,用户越来越多,传统的开 发方式一般都是所谓的单体架构(理解成一个单一的可执行程序),如果想增加一个业务,就要 向这个可执行程序中不断增加代码,显然,这个可执行程序一定会变得越来越复杂。当它复杂 到一定程度的时候,就会面临着可靠性、可维护性等都变差的问题。就像一个人,如果这个人 200斤还可以接受,如果1000斤,那这个人就麻烦了,他可能连独自站起来都做不到了。
微服务解决的就是这种单独一个可执行程序过度复杂、过度庞大的问题,把这个可执行 程序进行拆分,拆分的角度是从功能上进行,也就是说,从功能上拆分成多个小的程序,彼此 之间通过一些架构方式,配合起来共同实现业务需求。
微服务架构设计模式与本书所讲解的设计模式之间的差别:
-
① 单独一个可执行程序来实现业务也好,或者是采用微服务这种用多个可执行程序配 合来实现业务也罢,都存在首先要把一个一个单独的可执行程序写好的问题;
-
② 同时,并不是所有业务都能用微服务来解决。
所以,读者切不可因为微服务的存在就放弃了对写出高质量代码的追求。本书所指的 设计模式研究探讨的是针对一个单独的可执行程序内部的各个模块之间如何做到高灵活 性、高可复用性以及高可扩展性的问题,这一点,请读者明确。
三、设计模式分类
- 设计模式分类
常见设计模式大概有二十多种,通常分为三大类,见表1.1。
设计模式名称 | 设计模式分类 |
模板方法(Template Method)模式 | 行为型模式 |
策略(Strategy)模式 | 行为型模式 |
观察者(Observer)模式 | 行为型模式 |
命令(Command)模式 | 行为型模式 |
迭代器(Iterator)模式 | 行为型模式 |
状态(State)模式 | 行为型模式 |
中介者(Mediator)模式 | 行为型模式 |
备忘录(Memento)模式 | 行为型模式 |
职责链(Chain Of Responsibility)模式 | 行为型模式 |
访问者(Visitor)模式 | 行为型模式 |
解释器(Interpreter)模式 | 行为型模式 |
工厂模式:①简单工厂(Simple Factory)模式 ②工厂方法(Factory Method)模式 ③抽象工厂(Abstract Factory)模式 | 创建型模式 |
原型(Prototype)模式 | 创建型模式 |
建造者(Builder)模式 | 创建型模式 |
单件(Singleton)模式 | 创建型模式 |
装饰(Decorator)模式 | 创建型模式 |
外观(facade)模式 | 结构型模式 |
组合(Composite)模式 | 结构型模式 |
享元(Flyweight)模式 | 结构型模式 |
代理(Proxy)模式 | 结构型模式 |
适配器(Adapter)模式 | 结构型模式 |
桥接(Bridge)模式 | 结构型模式 |
- (1)行为型模式。这种模式关注的是对象的行为或者交互方面内容,主要涉及算法和 对象之间的职责分配。通过使用对象组合,行为型模式可以描述一组对象应该如何协作来完成一个整体任务。
- (2)创建型模式。这种模式关注的是如何创建对象,其核心思想是要把对象的创建和 使用相分离(解耦)以取代传统对象创建方式可能导致的代码修改和维护上的问题。
- (3)结构型模式。这种模式关注的是对象之间的关系,主要涉及如何组合各种对象以 便获得更加灵活的结构,例如,继承机制提供了最基本的子类扩展父类的功能,但结构型模 式不仅仅简单地使用继承,而是更多地通过各种关系组合以获得更加灵活的程序结构,达到 简化设计的目的。
相关文章:
【设计模式】设计模式介绍
一、设计模式概述 设计模式分很多种,每种一般都用于解决某个软件开发过程中的问题。许多人认为设 计模式有23种,其实,对于这个数字也没必要那么教条,当然还有更多的设计模式种类,只 不过是这23种比较经典而已。甚至可…...
图形学面试题总结
图形学面试题总结 文章目录 图形学面试题总结Opengl 与 Vulkan1、OpenGL的渲染管线有哪些主要阶段?分别做什么?2、OpenGL中的VAO、VBO和EBO分别是什么?为什么需要它们?3、细分着色器与几何着色器是什么4、Vulkan与Opengl的区别是什…...
Spring Cloud Alibaba 实战:Sentinel 保障微服务的高可用性与流量防护
1.1 Sentinel 作用 Sentinel 是阿里巴巴开源的一款 流量控制和熔断降级 框架,主要用于: 流量控制:限制 QPS,防止流量暴增导致系统崩溃熔断降级:当某个服务不可用时自动降级,避免故障扩散热点参数限流&…...
Comfyui 与 SDwebui
ComfyUI和SD WebUI是基于Stable Diffusion模型的两种不同用户界面工具,它们在功能、用户体验和适用场景上各有优劣。 1. 功能与灵活性 ComfyUI:ComfyUI以其节点式工作流设计为核心,强调用户自定义和灵活性。用户可以通过连接不同的模块&…...
面试之《前端常见的设计模式》
前端开发中运用多种设计模式可以提高代码的可维护性、可扩展性和可复用性。以下是一些常见的前端设计模式: 创建型模式 1. 单例模式 定义:确保一个类只有一个实例,并提供一个全局访问点。应用场景:在前端中,像全局状…...
PostgreSQL异常:An IO error occurred while sending to the backend
在使用PostgreSQL数据库批量写入数据的时候,遇到了一个问题,异常内容如下: Cause: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.报错内容 报错提示1 Caused by: org.postgresql.util.PSQLExc…...
嵌入式八股C语言---面向对象篇
面向对象与面向过程 面向过程 就是把整个业务逻辑分成多个步骤,每步或每一个功能都可以使用一个函数来实现面向对象 对象是类的实例化,此时一个类就内部有属性和相应的方法 封装 在C语言里实现封装就是实现一个结构体,里面包括的成员变量和函数指针,然后在构造函数中,为结构体…...
一周学会Flask3 Python Web开发-使用SQLAlchemy动态创建数据库表
锋哥原创的Flask3 Python Web开发 Flask3视频教程: 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili 前面我们定义了模型,我们可以通过sqlalchemy对象提供的create_all()方法来映射和动态创建数据库表。 因为我们用到…...
【spring】springAOP
1.基本概念 AOP即面向切面编程,它利用的是一种横切技术,解剖开封装的对象内部,并将那些影响多个类的公共行为封装到一个可重 用模块,这就是所谓的Aspect方面/切面。所谓的切面,简单点所说,就是将哪些与业务…...
解决VMware虚拟机CentOS 7 忘记登陆密码问题
1. 重启虚拟机,在重启时不停按E键进入初始化脚本编辑界面 2.在初始化脚本编辑界面,按↓键向下拉到最后,找到LANG/zh_CN.UTF-8那里,输入空格,接着添加 "init/bin/sh" 。然后按ctrlX键进入下一步。 3. 在界面中…...
如何在 Windows 10 启用卓越性能模式及不同电源计划对比
在使用 powercfg -duplicatescheme 命令启用 “卓越性能模式”(即 Ultimate Performance 模式)之前,有几个前提条件需要注意: 前提条件: 系统版本要求:卓越性能模式 仅在 Windows 10 专业版 或更高版本&a…...
基于 GEE 利用 Sentinel-2 数据反演叶绿素与冠层水分含量
目录 1 数据加载与预处理 2 叶绿素含量反演 3 冠层水分反演 4 数据可视化与导出 5 完整代码 6 运行结果 在生态学和环境科学领域,植被的健康状况是评估生态系统稳定性和功能的关键指标之一。而叶绿素含量和冠层水分含量作为反映植被生理状态的重要参数&#x…...
《鸿蒙系统下AI模型训练加速:时间成本的深度剖析与优化策略》
在当今数字化浪潮中,鸿蒙系统凭借其独特的分布式架构与强大的生态潜力,为人工智能的发展注入了新的活力。随着AI应用在鸿蒙系统上的日益普及,如何有效降低模型训练的时间成本,成为了开发者与研究者们亟待攻克的关键课题。这不仅关…...
PyTorch分布式训练
本文结构: 分布式训练概述环境设置数据并行(DDP)模型并行启动训练性能优化建议示例代码参考资料和相关问题 以下是为您整理的PyTorch分布式训练教程指南: 一、PyTorch分布式训练核心概念 数据并行:通过分割数据集实…...
ubuntu22.04 关于挂在设备为nfts文件格式无法创建软连接的问题
最近遇到情况,解压工程报错,无法创建软连接 但是盘内还有130G空间,明显不是空间问题,查找之后发现是移动硬盘的文件格式是NTFS,在ubuntu上不好兼容,于是报错。 开贴记录解决方案。 1.确定文件格式 使用命…...
C++编程:进阶阶段—4.2对象
目录 4.2 对象特征 4.2.1 构造函数和析构函数 4.2.2 构造函数的分类 4.2.3 拷贝函数调用时机 4.2.4 构造函数调用规则 4.2.5 深拷贝与浅拷贝 4.2.6 初始化列表 4.2.7 类对象作为类成员 4.2.8 静态成员 4.2.9 成员变量和成员函数的存储 4.2.10 this指针 4.2.11 空指针…...
C++跨平台开发环境搭建全指南:工具链选型与性能优化实战
C跨平台开发环境搭建全指南:工具链选型与性能优化实战 目录 开发环境搭建工具链选型性能优化实战常见问题排查 开发环境搭建 操作系统环境准备 Windows# 安装Visual Studio Build Tools choco install visualstudio2022buildtools choco install cmake --instal…...
常见JVM命令
1. java -XX:PrintCommandLineFlags HelloGC 作用:打印 JVM 启动时的命令行参数,包括用户显式设置的参数和 JVM 自动默认设置的参数。用于确认 JVM 实际使用的配置。 2. java -Xmn10M -Xms40M -Xmx60M -XX:PrintCommandLineFlags -XX:PrintGC -XX:Prin…...
C语言实现队列数据结构:思路与代码详解
目录 一、引言 二、整体思路 三、代码模块分析 (一)头文件包含与宏定义 (二)数据类型定义 (三)队列操作函数 1. 队列初始化 2. 队列销毁 3. 入队操作 4. 出队操作 5. 获取队头元素 6…...
【Docker项目实战】使用Docker与Caddy部署BanBan任务管理工具
【Docker项目实战】使用Docker部署BanBan任务管理工具 一、BanBan介绍1.1 BanBan简介1.2 主要特点1.3 使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载BanBan镜像五、…...
AI重构私域增长:从流量收割到终身价值运营的三阶跃迁
私域运营的AI进化论:内容即服务的三个阶段 随着企业微信生态的成熟,私域运营正经历从"流量收割"到"关系养成"的本质转变。在AIGC技术的推动下,2024年私域场景正式进入**"内容即服务"**的价值共创期࿱…...
es扩容节点以后写入数据量增加1倍
背景: es扩容一倍的数据节点以后 写入数据量增加1倍 业务反馈业务访问量没增加。 最后定位是监控数据: PUT _cluster/settings {"persistent": {"xpack.monitoring.collection.enabled" : "false"} }这个索引记录的是 节…...
Go本地缓存设计与实现
本地缓存是一个项目中很常见的组件。在很多人的眼中就是一个简单的key-value的map存储即可实现,但实际上,设计一个本地缓存需要考虑的问题远比你想象的多,比如说,本地缓存是将数据存储在内存,若数据量激增突破了内存限…...
04 | 初始化 fastgo 项目仓库
提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);本节课最终…...
Spring中复杂对象的创建方式:FactoryBean、实例工厂与静态工厂全解析
1.反转控制与依赖注入 控制:对于成员变量赋值的控制权 反转控制:把对于成员变量赋值的控制权,从代码中反转(转移)到Spring工厂和配置文件中完成 好处:解耦合 底层实现:工厂设计模式 依赖注入: 注入…...
异或和之和 第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组
异或和之和 题目来源 第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 A 组 原题链接 蓝桥杯 异或和之和 https://www.lanqiao.cn/problems/3507/learning/ 问题描述 问题分析 要点1:异或运算 概念 异或(Exclusive OR,简称 XOR)是一种数学运算符,常用于逻辑运算与计算机…...
设计模式 一、软件设计原则
一、理解设计原则 1、单一原则 1.1 如何理解单一职责原则(SRP) 单一职责原则(Single Responsibility Principle,简称SRP),他要求一个类或模块应该只负责一个特定的功能,这有助于降低类之间的耦合度…...
修复Electron项目Insecure Content-Security-Policy(内容安全策略CSP)警告的问题
将以下代码粘贴进html的<header>标签内 <metahttp-equiv"Content-Security-Policy"content"default-src self; style-src self unsafe-inline; img-src self data:; "> 解释一下上面代码中的属性含义 default-src self:配置加载策…...
机器人交互系统 部署构建
环境要求 Ubuntu 20.04 或更高版本ROS Noetic 或兼容版本Python 3.8 安装步骤 1. 安装ROS环境(如未安装) sudo apt update sudo apt install ros-noetic-desktop-full source /opt/ros/noetic/setup.bash2. 创建工作空间并克隆代码 mkdir -p ~/code…...
当AI回答问题时,它的“大脑”里在炒什么菜?
文章目录 1. 拆解订单:AI如何听懂你的“暗号”?2. 调用工具:AI的“万能工具箱”里有什么?3. 知识不够?去“图书馆”现学现卖!4. 人类的秘密武器:给AI戴上“镣铐”5. 为什么AI会“胡言乱语”&…...
linux 软件扩展GPU显存
概述 共享内存可以通过 Unified Memory(统一内存)来实现,它允许 CPU 和 GPU 共享相同的内存地址空间,从而方便数据的传输和访问。 利用该技术可解决家用GPU 机器学习时显存不足的问题 (注: 虽然解决了爆显…...
【RabbitMQ】Spring Boot 结合 RabbitMQ 完成应用间的通信
🔥个人主页: 中草药 🔥专栏:【中间件】企业级中间件剖析 Spring 框架与 RabbitMQ 的整合主要通过 Spring AMQP(Advanced Message Queuing Protocol)模块实现,提供了便捷的消息队列开发能力。 引…...
DeepSeek本地化部署(DeepSeek+olloma+Dify)
文章目录 概要需要准备的工具Ollama准备内容Docker准备内容Dify准备内容本地访问Dify 概要 提示:本篇文章主要讲述如何部署本地Deepseek私有大模型,使用Windows无显卡环境进行部署 需要准备的工具 Ollama、Docker Desktop 下载地址: Ollama…...
Spring boot3-WebClient远程调用非阻塞、响应式HTTP客户端
来吧,会用就行具体理论不讨论 1、首先pom.xml引入webflux依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId> </dependency> 别问为什么因为是响应式....…...
Ubuntu22.04安装数据
数据库安装步骤: sudo apt-get update sudo apt install mysql-server mysql-client sudo systemctl start mysql sudo systemctl status mysql (1)在命令行登录 MySQL 数据库,并使用 mysql 数据库 (必须使用这个…...
【python-uiautomator2】手机上的ATX应用界面报错问题处理:无法提供服务,非am instrument启动
目录 一、前期准备 1.1 插入设备 1.2 安装atx-agent 二、解决报错:无法提供服务,非am instrument启动 2.1 出现报错 2.2 尝试解决 2.3 最终解决 三、开启ATX的悬浮窗权限 一、前期准备 1.1 插入设备 本地插入待执行设备,待执行设备…...
自动化测试介绍及学习路线
目录 一、自动化测试 1.1 自动化测试的概念 1.2 自动化测试的主流领域 接口自动化测试 UI自动化测试 持续集成 二、学习路线 一、自动化测试 1.1 自动化测试的概念 自动化测试是指利用软件工具或脚本来执行测试用例和比较实际结果与预期结果的过程,通过运行…...
Python:函数(一)
python函数相关的知识点 1. 函数定义与调用 定义:使用 def 关键字,后接函数名和参数列表。 def greet(name):"""打印问候语(文档字符串)"""print(f"Hello, {name}!") 调用:…...
qml c++混合编程注意事项
在Qml和C类进行数据交互时,通用的办法都是注册C到Qml中,但是很多时候C的对象是在C中进行创建,如果在Qml中创建了,数据之间的交互就会出现无法控制的问题。 信号与槽、上下文等都是数据交互的方式,但是当嵌套多层时&…...
Leetcode6-Z字形变换
题目链接:6. Z 字形变换 - 力扣(LeetCode) 思路: 定义numRows个字符数组,用于存每一行的字符;再定义一个标志行数的变量cnt,cnt在0到numRows-1之间不停的加一或减一(当cnt到0了&am…...
【eNSP实战】配置交换机端口安全
拓扑图 目的:让交换机端口与主机mac绑定,防止私接主机。 主机PC配置不展示,按照图中配置即可。 开始配置之前,使用PC1 ping 一遍PC2、PC3、PC4、PC5,让交换机mac地址表刷新一下记录。 LSW1查看mac地址表 LSW1配置端…...
React.js 基础与进阶教程
React.js 基础与进阶教程 React.js 是由 Facebook 开发的流行前端 JavaScript 库,专为构建用户界面(UI)设计,尤其适用于单页面应用(SPA)。它采用组件化开发模式,使 UI 结构更加清晰、可维护性更…...
Docker基础入门(一)
初识Docker 什么是Docker Docker是一个快速交付应用、运行应用的技术: 可以将程序及其依赖、运行环境一起打包为一个镜像,可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离容器,各个应用互不干扰启动、移除都可以通过一行命令完成&…...
moment.js时间处理库
目录 一、moment().isValid()验证时间是否有效 二、moment().second()获取秒数或者设置秒数 三、moment().day()获取星期或者设置星期 四、moment().add()加法操作 五、moment().subtract()减法操作 六、moment.max()最大值 七、moment.min()最小值 八、克隆时间 一、mo…...
基于hive的电信离线用户的行为分析系统
标题:基于hive的电信离线用户的行为分析系统 内容:1.摘要 随着电信行业的快速发展,用户行为数据呈现出海量、复杂的特点。为了深入了解用户行为模式,提升电信服务质量和精准营销能力,本研究旨在构建基于 Hive 的电信离线用户行为分析系统。通…...
循环神经网络(RNN):时序建模的核心引擎与演进之路
在人工智能处理序列数据的战场上,循环神经网络(RNN)如同一个能够理解时间的智者。从 2015 年谷歌神经机器翻译系统颠覆传统方法,到 2023 年 ChatGPT 实现对话连续性,这些突破都植根于 RNN 对时序建模的深刻理解。本文将…...
docker 安装常用镜像
我们在上篇文章中已经修改了daemon.json 安装镜像时如果search超时就直接pull 安装mysql docker pull mysql:5.7 启动命令 docker run --name mysql-docker -p 3306:3306 -e MYSQL_ROOT_PASSWORDroot1234 -d mysql:5.7 ocker run:运行docker容器命令 --name my…...
大数据学习(63)- Zookeeper详解
&&大数据学习&& 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言📝支持一下博主哦🤞 …...
安卓Compose中accompanist库使用详解
安卓Compose中accompanist库使用详解 文章目录 安卓Compose中accompanist库使用详解一、Accompanist 库概览二、核心组件详解三、总结与建议 本文首发地址 https://h89.cn/archives/348.html 最新更新地址 https://gitee.com/chenjim/chenjimblog 一、Accompanist 库概览 Acco…...
Gateway:网关路由与登录鉴权
在微服务架构中,用户登录和身份校验的处理方式确实与单体应用有所不同。在单体架构中,一旦用户通过身份验证,其会话信息可以在整个应用范围内共享,所有模块都能访问到用户信息。然而,在微服务架构下,每个服…...