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

深入理解设计模式:设计模式定义、设计原则以及组织编目

文章目录

  • 一、设计模式
    • 1.1 设计模式的起源
    • 1.2 设计模式的定义
    • 1.3 记录要素
    • 1.4 合理使用模式
  • 二、设计模式的六大原则
    • 2.1 开闭原则(Open-Closed Principle, OCP)
      • 2.1.1 定义
      • 2.1.2 原则分析
      • 2.1.3 开闭原则的意义所在
    • 2.2 单一职责原则(Single Responsibility Principle, SRP)
      • 2.4.1 定义
      • 2.4.2 原则分析
    • 2.3 里氏代换原则(Liskov Substitution Principle, LSP)
      • 2.3.1 定义
      • 2.3.2 原则分析
    • 2.4 依赖倒转原则(Dependency Inversion Principle, DIP)
      • 2.4.1 定义
      • 2.4.2 原则分析
    • 2.5 合成复用原则(Composite Reuse Principle, CRP)
      • 2.5.1 定义
      • 2.5.2 原则分析
    • 2.6 迪米特法则(Law of Demeter, LoD)
      • 2.6.1 定义
      • 2.6.2 原则分析
  • 三、设计模式的分类
    • 3.1 创建型模式
    • 3.2 结构型模式
    • 3.3 行为型模式
  • 参考资料

一、设计模式

1.1 设计模式的起源

软件领域的设计模式起源主要是受到1977年建筑大师Alexander出版的《A Pattern Language:Towns, Building, Construction》一书。Alexander在其著作中将其建筑行业中的许多问题的最佳解决方案记录为200多种模式,其思想不仅在建筑行业影响深远,而且很快影响到了软件设计领域。

1987年,Kent Beck和Ward Cunningham将Alexander在建筑学上的模式观点应用于软件设计,开发了一系列模式,并用Smalltalk语言实现了雅致的用户界面。Kent Beck和Ward Cunningham在1987年举行的一次面向对象的会议上发表了论文:《在面向对象编程中使用模式》,该论文发表后,有关软件的设计模式论文以及著作相继出版。

目前,被公认在设计模式领域最具影响力的著作是Erich Gamma、Richard Helm、Ralph Johnson和John Vlissides在1994年合作出版的著作:《DesignPatterns: Elements of Reusable Object-OrientedSoftware》(中译本《设计模式:可复用的面向对象软件的基础》或《设计模式》),该书提出了23种基本设计模式,被广大喜爱者昵称为GOF (Gang of Four)之书,被认为是学习设计模式的必读著作。GOF之书已经被公认为是设计模式领域的奠基之作

时至今日,在可复用面向对象软件发展过程中,新的设计模式仍然在涌现,丰富着软件设计领域的知识和实践。

1.2 设计模式的定义

设计模式(pattern)是从许多优秀的软件系统中总结出的成功的可复用的设计方案。

软件模式:

•对通用设计问题的重复解决方案

•对真实世界问题的实践的/具体的解决方案

•面向特定的问题环境

•权衡利弊之后得到的“最佳”解决方案

•领域专家和设计老手的“杀手锏”

•用文档的方式记录的最佳实践

•在讨论问题的解决方案时,一种可交流的词汇

•在使用(重用)、共享、构造软件系统中,一种有效地使用已有的智慧/经验/专家技术的方式

1.3 记录要素

记录一个设计模式需有四个基本要素:

1.名称 一个模式的名称高度概括该模式的本质,有利于该行业统一术语、便于交流使用。

2.问题 描述应该在何时使用模式,解释设计问题和问题存在的前因后果,描述在怎样的环境下使用该模式。

3.方案 描述设计的组成部分,它们之间的相互关系及各自的职责和协作方式。

4.效果 描述模式的应用效果及使用模式应当权衡的问题。主要效果包括使用模式对系统的灵活性、扩充性和复用性的影响。

例如,GOF之书如下记录中介者模式:

名称 中介者

问题 用一个中介者来封装一系列的对象交互。中介者使各对象不需要显示地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

方案 中介者(Mediator)接口、具体中介者(ConcreteMediator)、同事(Colleague)、具体同事(ConcreteColleague)。

效果 减少了子类的生成、将各个同事解耦、简化了对象协议、控制集中化。

事实上,关于如何描述设计模式,《设计模式:可复用的面向对象软件的基础》有更多的细节,

1.4 合理使用模式

不是软件的任何部分都需要套用模式来设计的,必须针对具体问题合理的使用模式。

1. 正确使用

当你设计某个系统,并确认所遇到的问题刚好适合使用某个模式,就可以考虑使用该模式到你的系统设计中,毕竟该模式已经被公认是解决该问题的成功方案,能使设计的系统易维护、可扩展性强、复用性好,而且这些经典的模式也容易让其他开发人员了解你的系统和设计思想。

2. 避免教条

模式不是数学公式、也不是物理定律、更不是软件设计中的“法律”条文,一个模式只是成功解决某个特定问题的设计方案,你完全可以修改模式中的部分结构以符合你的设计要求。

3.模式挖掘

​ 模式不是用理论推导出来的,而是从真实世界的软件系统中被发现、按着一定规范总结出来的可以被复用的方案。许多文献或书籍里阐述的众多模式实际上都是GOF书中经典模式的变形,这些变形模式都经过所谓的“三次规则”,即该模式已经在真实世界的三个方案中被成功的采用。可以从某个系统中洞察出某种新模式,只要经过“三次规则”就会被行业认可。

4.避免乱用

​ 不是所有的设计中都需要使用模式,因为模式不是发明出来的,而是总结出来的,事实上,真实世界中的许多设计实例都没有使用过GOF之书中的经典模式。在进行设计时,尽可能用最简单的方式满足系统的要求,而不是费尽心机地琢磨如何在这个问题中使用模式,一个设计中,可能并不需要使用模式就可以很好地满足系统的要求,如果牵强地使用某个模式可能会在系统中增加许多额外的类和对象,影响系统的性能,因为大部分设计模式往往会在系统中加入更多的层,这不但增加复杂性,而且系统的效率也会下降。

5.了解反模式

​ 所谓反模式就是从某些软件系统中总结出的不好的设计方案,反模式就是告诉你如何采用一个不好的方案解决一个问题。既然是一个不好的方案,为何还有可能被重复使用呢?这是因为,这些不好的方案表面上往往有很强的吸引力,人们很难一眼就发现它的弊端,因此,发现一个反模式也是非常有意义的工作。在有了一定的设计模式的基础之后,你可以用搜索引擎查找有关反模式的信息,这对于学习好设计模式也是非常有帮助的。

二、设计模式的六大原则

2.1 开闭原则(Open-Closed Principle, OCP)

2.1.1 定义

开闭原则定义: 一个软件实体应当对扩展开放,对修改关闭。即在设计一个模块的时候,应当使这个模块可以在不被修改的前提下被扩展,即实现在不修改源代码的情况下改变这个模块的行为。

开闭原则由Bertrand Meyer于1988年提出,它是面向对象设计中最重要的原则之一。在开闭原则的定义中,软件实体可以指一个软件模块、一个由多个类组成的局部结构或一个独立的类。

2.1.2 原则分析

事实上完全封闭的系统是不存在的。无论模块怎样实现封闭,到最后,总还是有一些无法封闭的变化。而对应的思路就是: 既然不能做到绝对封闭,那我们就应该选择对哪些变化进行封闭,哪些变化进行隔离。然后将那些无法封闭的变化抽象出来,进行隔离,并且允许扩展,尽可能地减少系统的开发。当系统变化出现时要能够及时地作出反应。

开放-封闭原则提供了一个使系统在面对需求变更时,可以保持系统相对稳定的解决方案。其思想简单来说就是面对需求的变化,通过添加新的类或者模块等就可以应对,而无需对原有的代码进行修改

2.1.3 开闭原则的意义所在

只依赖于抽象,实现开放-封闭原则的核心思想就是 面向抽象编程,而不是面向具体编程。

因为抽象相对来说是稳定的。让类去依赖于固定的抽象,所以对于修改来说就是封闭的;而通过面向对象的继承以及多态机制,可以去实现对抽象体的继承,通过重写其方法来改变固有行为,从而实现新的扩展方法,所以对于来说扩展就是开放的。这是实施开放-封闭原则的基本思路。

同时这种机制也是建立在两个基本的设计原则基础上,这就是里氏代换原则和合成复用原则。可以简单地理解为,开闭原则是面向对象设计的目标,里氏代换原则和依赖倒转原则就是面向对象设计的主要手段

2.2 单一职责原则(Single Responsibility Principle, SRP)

2.4.1 定义

单一职责原则主要有以下两种定义:

  • 一个对象应该只包含单一的职责,并且该职责被完整地封装在一个类中。
  • 就一个类而言,应该仅有一个引起它变化的原因

2.4.2 原则分析

一个类(或者大到模块,小到方法)承担的职责越多,它被复用的可能性越小,而且如果一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作。

单一职责原则是实现高内聚、低耦合的指导方针,在很多代码重构手法中都能找到它的存在,它是最简单但又最难运用的原则,需要设计人员发现类的不同职责并将其分离,而发现类的多重职责需要设计人员具有较强的分析设计能力和相关重构经验。

2.3 里氏代换原则(Liskov Substitution Principle, LSP)

2.3.1 定义

里氏代换原则主要有以下两种定义:

  • 如果对每一个类型为S的对象o1,都有类型为T的对象o2,使得以T定义的所有程序P在所有的对象o1都代换成o2时,程序P的行为没有变化,那么类型S是类型T的子类型。
  • 所有引用基类(父类)的地方必须能透明地使用其子类的对象

2.3.2 原则分析

里氏代换原则可以通俗表述为: 在软件中如果能够使用基类对象,那么一定能够使用其子类对象。把基类都替换成它的子类,程序将不会产生任何错误和异常,反过来则不成立,如果一个软件实体使用的是一个子类的话,那么它不一定能够使用基类。

里氏代换原则是实现开闭原则的重要方式之一,由于使用基类对象的地方都可以使用子类对象,因此在程序中尽量使用基类类型来对对象进行定义,而在运行时再确定其子类类型,用子类对象来替换父类对象。

2.4 依赖倒转原则(Dependency Inversion Principle, DIP)

2.4.1 定义

依赖倒转原则定义:

  • 高层模块不应该依赖低层模块,但两者都应该依赖抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

可以简单地理解为,要针对接口编程,不要针对实现编程

2.4.2 原则分析

面向对象设计最重要的原则就是创建抽象化,同时从抽象化导出具体化,具体化给出不同的实现。继承的关系就是一种从抽象化到具体化的实现。抽象层所包含的应该是应用系统的商务逻辑和宏观的、对整个系统来说具有重要的战略性的决定,也是必然性的体现。具体的层次含有的是一些次要的与实现有关的算法以及逻辑,还有战术性的决定,这些都带有相当大的偶然性选择。具体层次的代码都是经常变动的,也就无法避免出现错误。

从复用的角度来说,高层次的模块是应当被复用的,而且会是被复用的重点,因为它含有一个应用系统最重要的宏观逻辑,并且较为稳定。而在传统的过程性设计当中,复用则侧重于具体层次模块的复用。依赖倒转原则正是对传统的过程性设计方法的“倒转”,也是高层次模块复用及其可维护性的最有效的规范。

2.5 合成复用原则(Composite Reuse Principle, CRP)

2.5.1 定义

合成复用原则定义:尽量使用对象组合,而不是继承来达到复用的目的

合成复用原则又称为组合/聚合复用原则(Composition/ Aggregate Reuse Principle, CARP)

合成与聚合都是特殊的关联种类。聚合表示比较“弱”的拥有关系,具体表现是甲对象中可以包括乙对象,但乙对象不是甲对象的一部分;合成则是一种比较“强”的拥有关系,体现的是严格的整体与部分之间的关系,并且整体与部分有相同的生命周期。比如鱼和鱼群是聚合关系,手臂与人体之间则是部分与整体的关系。
优先使用对象的合成/聚合会有助于保持系统的每个类都会被封装,并且类被集中在单个任务上。这样类和类之间的继承层次就可以保持比较小的规模,并且不太可能增长为不可控制的巨大单位。

2.5.2 原则分析

如果语义上存在着明确的“Is-A”关系,并且这种关系是稳定的且不变的,则我们考虑使用继承; 如果没有“Is-A”的关系,或者这种关系是可变的时,我们使用合成。

当两个类都能符合里氏代换原则时,这两个类才可以是“Is-A”的关系。也就是说,如果两个类之间的关系是“Has-A”,但是这两个类被设计为继承,则这两个类肯定会违背里氏代换原则。

2.6 迪米特法则(Law of Demeter, LoD)

2.6.1 定义

迪米特法则(Law of Demeter, LoD)常见定义如下:

  • 不要和“陌生人”说话
  • 只与你的直接朋友通信
  • 每一个软件单位对其他的单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单位
  • 如果两个类之间不必直接通信,则这两个类不应该发生直接的相互作用。如果其中的一个类需要调用另一个类的某个方法,可以通过第三方来转发这个调用。

迪米特法则的根本思想,是强调类之间需要尽量多实现松散耦合。类之间的耦合越弱,越有利于复用,一个处在弱耦合的类被修改,不会对有关系的类造成波及,反之则会导致很多麻烦。 信息的隐藏会促进软件的复用。

2.6.2 原则分析

迪米特法则强调的前提是在类的结构设计上,每一个类都要尽量降低成员的访问权限,类自己包装好自己的private状态,不需要让别的类知道的字段或者行为就不要公开

三、设计模式的分类

根据目的准则,模式依据其目的可分为创建型(Creational)、结构型(Structural)、或行为型(Behavioral)三种。创建型模式与对象的创建有关;结构型模式处理类或对象的组合;行为型模式对类或对象怎样交互和怎样分配职责进行描述。

3.1 创建型模式

创建型模式抽象了实例化过程。它们帮助一个系统独立于如何创建、组合和表示它的那些对象。一个类创建型模式使用继承改变被实例化的类,而一个对象创建型模式将实例化委托给另一个对象。

创建型模式主要包括:

  1. 工厂方法模式(Factory Method Pattern): 工厂方法模式定义一个用于创建对象的接口,但将实际的对象创建延迟到子类中。这样,不同的子类可以创建具体不同类型的对象,而客户端代码仅与抽象工厂接口进行交互,实现了解耦。它适用于需要根据不同条件创建不同类型对象的情况。
  2. 抽象工厂模式(Abstract Factory Pattern): 抽象工厂模式提供一个接口,用于创建一系列相关或相互依赖的对象家族,而不需要指定具体的类。客户端通过使用抽象工厂接口,可以创建和使用这些对象,而无需关心具体的实现类。它适用于需要创建一组相关对象的场景。
  3. 单例模式(Singleton Pattern): 单例模式确保一个类只有一个实例,并提供一个全局访问点来获取该实例。这在需要全局唯一实例的场景下很有用,比如配置信息、日志记录器等。
  4. 建造者模式(Builder Pattern): 建造者模式将一个复杂对象的构建过程和表示分离,使得同样的构建过程可以创建不同的表示。通过使用指挥者来统一组织构建过程,客户端可以创建出不同配置的对象。
  5. 原型模式(Prototype Pattern): 原型模式通过复制现有的对象来创建新的对象实例,而不是通过实例化类来创建。它允许通过克隆的方式来创建新的对象,减少了对象创建的开销。

3.2 结构型模式

结构型模式涉及到如何组合类和对象以获得更大的结构,以解决对象之间的组合和接口问题结构型类模式采用继承机制来组合接口或实现。一个简单的例子是采用多重继承方法将两个以上的类组合成一个类,结果这个类包含了所有父类的性质。这一模式尤其有助于多个独立开发的类库协同工作。结构型对象模式不是对接口和实现进行组合,而是描述了如何对一些对象进行组合,从而实现新功能的一些方法。因为可以在运行时刻改变对象组合关系,所以对象组合方式具有更大的灵活性,而这种机制用静态类组合是不可能实现的。

结构性模式主要包括:

  1. 适配器模式(Adapter Pattern): 适配器模式允许将一个类的接口转换为另一个类的接口,以便两者可以一起工作。它在不改变原有类接口的情况下,使得原本不兼容的类可以一起协作。
  2. 装饰器模式(Decorator Pattern): 装饰器模式允许动态地给对象添加额外的功能,而不影响其结构。通过将对象放入装饰器中,可以以透明的方式扩展对象的功能。
  3. 代理模式(Proxy Pattern): 代理模式用于控制对另一个对象的访问。它在客户端和目标对象之间引入了一个代理对象,可以用于增加额外的控制或管理目标对象的访问。
  4. 外观模式(Facade Pattern): 外观模式提供了一个简化的接口,用于访问复杂系统的一组接口。通过外观模式,客户端可以更方便地使用系统,而不需要了解底层复杂的实现。
  5. 桥接模式(Bridge Pattern): 桥接模式将抽象部分与实现部分分离,使得它们可以独立地变化。通过桥接模式,可以避免在类之间使用多重继承,提高了系统的灵活性。
  6. 组合模式(Composite Pattern): 组合模式用于将对象组合成树状结构,以表示部分-整体的层次关系。通过组合模式,可以使得客户端统一地处理单个对象和组合对象。
  7. 享元模式(Flyweight Pattern): 享元模式用于减少对象的创建,通过共享相同的对象来降低内存的消耗。它适用于需要创建大量相似对象的场景。

3.3 行为型模式

行为模式涉及到算法和对象间职责的分配。行为模式不仅描述对象或类的模式,还描述它们之间的通信模式。这些模式刻划了在运行时难以跟踪的复杂的控制流。它们将你的注意力从控制流转移到对象间的联系方式上来

行为型模式主要包括:

  1. 观察者模式(Observer Pattern): 观察者模式定义了对象之间的一对多依赖关系,当一个对象的状态发生变化时,其所有依赖者都会收到通知并自动更新。这种模式使得对象之间的关联变得松散,增加了系统的可维护性和扩展性。
  2. 策略模式(Strategy Pattern): 策略模式定义了一系列的算法,并使它们可以互相替换,使得算法可以独立于客户端而变化。客户端可以根据需要选择使用不同的策略,从而实现灵活的算法组织和切换。
  3. 模板方法模式(Template Method Pattern): 模板方法模式定义了一个算法的骨架,将一些步骤的实现延迟到子类中。这样,不同的子类可以实现算法的具体细节,而不改变算法的整体结构。
  4. 命令模式(Command Pattern): 命令模式将请求封装为一个对象,从而使得客户端可以参数化不同的请求,并支持对请求进行排队、记录和撤销。这样,可以实现请求的发起者和接收者之间的解耦。
  5. 责任链模式(Chain of Responsibility Pattern): 责任链模式通过将多个对象组成一条责任链,依次处理请求,直到请求被处理。这样,可以动态地改变请求的处理顺序,实现请求发送者与接收者之间的解耦。
  6. 迭代器模式(Iterator Pattern): 迭代器模式提供一种顺序访问聚合对象的方法,而无需暴露其内部表示。这样,可以在不影响聚合对象的情况下遍历聚合对象的元素。
  7. 备忘录模式(Memento Pattern): 备忘录模式用于在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样,在后续需要时可以恢复对象到之前的状态。

参考资料

《设计模式:可复用的面向对象软件的基础》(设计模式奠基之作)

《设计模式其实很简单》(设计模式的设计原则讲得很清楚)

相关文章:

深入理解设计模式:设计模式定义、设计原则以及组织编目

文章目录 一、设计模式1.1 设计模式的起源1.2 设计模式的定义1.3 记录要素1.4 合理使用模式 二、设计模式的六大原则2.1 开闭原则(Open-Closed Principle, OCP)2.1.1 定义2.1.2 原则分析2.1.3 开闭原则的意义所在 2.2 单一职责原则(Single Responsibility Principle, SRP)2.4.1…...

鸿鹄协助管理华为云与炎凰Ichiban

炎凰对华为云的需求 在炎凰日常的开发中,对于服务器上的需求,我们基本都是采用云服务。目前我们主要选择的是华为云,华为云的云主机比较稳定,提供的云主机配置也比较多样,非常适合对于不同场景硬件配置的需求&#xff…...

Vite创建Vue+TS项目引入文件路径报错

使用vite搭建vue3脚手架的时候,发现main.ts中引入App.vue编辑器会报错,但是不影响代码运行。 报错信息:TS2307: Cannot find module ‘./App.vue’ or its corresponding type declarations. 翻译过来是找不到模块或者相关的声明类型&#…...

计算机里基本硬件的组成以及硬件协同

文章目录 冯诺依曼体系输入设备输出设备存储器运算器控制器协同工作的流程 冯诺依曼体系 世界上第一台通用计算机,ENIAC,于1946年诞生于美国一所大学。 ENIAC研发的前期,需要工作人员根据提前设计好的指令手动接线,以这种方式输入…...

2023软件设计师中级备考经验分享(文中有资料链接分享)

先摊结论吧,软考中级设计师备考只是备考半个月(期间还摆烂了几天),然而成绩如下: 我自己都没想到会这么好的成绩。。。 上午题:推荐把软考通APP里的历年真题刷3-4遍,直接刷真题,然后…...

Windows 10 中无法最大化任务栏中的程序

方法1:仅选择选项 PC 屏幕 如果您使用双显示器,有时这可能会发生在您的 1 台计算机已插入但您正在访问的应用程序正在另一台计算机上运行的情况下,因此您看不到任何选项。因此,请设置仅在主计算机上显示显示的 PC 屏幕选项。 第…...

【iOS】KVOKVC原理

1 KVO 键值监听 1.1 KVO简介 KVO的全称是Key-Value Observing,俗称"键值监听",可以用于监听摸个对象属性值得改变。 KVO一般通过以下三个步骤使用: // 1. 添加监听 [self.student1 addObserver:self forKeyPath:"age"…...

当机器人变硬核:探索深度学习中的时间序列预测

收藏自:Wed, 15 Sep 2021 10:32:56 UTC 摘要:时间序列预测是机器学习和深度学习领域的一个重要应用,它可以用于预测未来趋势、分析数据模式和做出决策。本文将介绍一些基本概念和常用方法,并结合具体的案例,展示如何使…...

C# Solidworks二次开发:自动创建虚拟零件及使用注意事项

今天要讲的是关于在solidworks中如何自动创建虚拟零件的功能,也就是solidworks中插入新零件这个功能。 实现这个功能需要使用的API如下所示: InsertNewVirtualPart(swFaceOrPlane1, out swcomp2); 其中这个方法中使…...

vim工具 windows系统使用

vim常用命令: 编辑–>输入: i: 在当前光标所在字符的前面,转为输入模式; 粘贴命令 p p: 如果删除或复制为整行内容,则粘贴至光标所在行的下方,如果复制或删除的内容为非整行,则粘贴至光标所…...

Tesseract开源的OCR工具及python pytesseract安装使用

一 、介绍 Tesseract是一款由Google赞助的开源OCR。 pytesseract是python包装器,它为可执行文件提供了pythonic API。 Tesseract 已经有 30 年历史,开始它是惠普实验室的一款专利软件,在2005年后由Google接手并进一步开发和完善。Tesseract支…...

【数理知识】自由度 degree of freedom 及自由度的计算方法

放在最前的一句话:自由度是一个存在于两个学科中的概念,一个是存在于统计学中的自由度,另一个是存在于物理学中的自由度。而我本人需要的是研究物理学中的自由度概念,同时本笔记全篇也是在了解物理学中的自由度。 文章目录 自由度…...

苍穹外卖day09——历史订单模块(用户端)+订单管理模块(管理端)

查询历史订单——需求分析与设计 产品原型 业务规则 分页查询历史订单 可以根据订单状态查询 展示订单数据时,需要展示的数据包括:下单时间、订单状态、订单金额、订单明细(商品名称、图片) 接口设计 查询历史订单——代码开…...

正则表达式 —— Grep

文本处理三剑客:Grep、Sed、Awk 这三个工具都是基于对文本的内容进行增删改查的操作,此篇着重介绍grep与正则表达式的应用,以及扩展正则表达式。 正则表达式 什么是正则表达式? 它是由一类特殊字符以及文本字符所编写的一种模式…...

STC12C5A系列单片机片内看门狗的应用

wdt.c #include "wdt.h"void wdt_init(void) {WDT_CONTR 0x24; // 0010 0100 - 1.1377s }void wdt_feed(void) {WDT_CONTR | 0x10; // 喂狗 }wdt.h #ifndef _WDT_H_ #define _WDT_H_#include "stc12c5a60s2.h"// 函数声明 extern void wdt_init(void); …...

C语言指针详解

目录 指针是什么? 指针和指针类型 指针-整数 指针的解引用 野指针 野指针成因 如何规避野指针 指针运算 指针- 整数 指针-指针 指针的关系运算 指针和数组 二级指针 指针数组 指针数组 模拟二维数组 指针是什么? 指针理解的2个要点: 1. 指针是内存中一个…...

RTPS规范v2.5(中文版)

实时发布订阅协议 DDS互操作性有线协议 (DDSI-RTPS) 技术规范 V2.5 (2022-04-01正式发布) https://www.omg.org/spec/DDSI-RTPS/2.5/PDF   目 录 1 范围 8 2 一致性 8 3 规范性参考文献 8 4 术语和定义 9 5 标识 …...

LeetCode102.Binary-Tree-Level-Order-Traversal<二叉树的层序遍历>

题目: 思路: 写过N叉树的层序遍历,(8条消息) LeetCode429.N-Ary-Tree-Level-Order-Traversal<N 叉树的层序遍历>_Eminste的博客-CSDN博客 使用栈保存每一层的结点。然后每次当前层结束。将这一层的值添加进去res中。…...

yolov8系列[五]-项目实战-yolov8模型无人机检测

yolov8系列[五]-项目实战-yolov8模型无人机检测 项目介绍项目展示功能简介代码结构如何启动 开发者模式1. 安装依赖环境2. 启动程序 源代码下载其他 项目介绍 无人机识别项目,无人机搭载nvidia jetson边缘计算板子,进行实时识别。使用yolov8算法,训练了识别无人机的…...

Redis 笔记,基本数据类型、持久化、主从、集群等等问题

标题 😀😀😀创作不易,各位看官点赞收藏. 文章目录 标题Redis 基础笔记1、安装及环境搭建2、Redis 数据类型2.1、String2.2、List2.3、Hash2.4、Set2.5、Zset2.6、BitMap2.7、HyperLogLog2.8、Geospatial2.9、Stream 3、Redis 持久…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)&#xff0…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

uniapp 字符包含的相关方法

在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

MyBatis中关于缓存的理解

MyBatis缓存 MyBatis系统当中默认定义两级缓存:一级缓存、二级缓存 默认情况下,只有一级缓存开启(sqlSession级别的缓存)二级缓存需要手动开启配置,需要局域namespace级别的缓存 一级缓存(本地缓存&#…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

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

2025-05-08-deepseek本地化部署

title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...

Selenium 查找页面元素的方式

Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素,以下是主要的定位方式: 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...

【工具教程】多个条形码识别用条码内容对图片重命名,批量PDF条形码识别后用条码内容批量改名,使用教程及注意事项

一、条形码识别改名使用教程 打开软件并选择处理模式:打开软件后,根据要处理的文件类型,选择 “图片识别模式” 或 “PDF 识别模式”。如果是处理包含条形码的 PDF 文件,就选择 “PDF 识别模式”;若是处理图片文件&…...