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

文章目录

  • 一、设计模式
    • 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): 备忘录模式用于在不破坏封装性的前提下,捕获一个对象的内部状态,并在对象之外保存这个状态。这样,在后续需要时可以恢复对象到之前的状态。

参考资料

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

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

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

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

相关文章

Tomcat的基本使用,如何用Maven创建Web项目、开发完成部署的Web项目

Tomcat 一、Tomcat简介二、Tomcat基本使用三、Maven创建Web项目3.1 Web项目结构3.2开发完成部署的Web项目3.3创建Maven Web项目3.3.1方式一3.3.2方式二(个人推荐) 总结 一、Tomcat简介 Web服务器: Web服务器是一个应用程序(软件&…

android数据的储存、文件的储存、SharedPreferences储存、SQLite的基本用法

一、文件的储存 1、将数据储存到文件中 Context类中提供了openfileOutput()方法,用来获取一个文件流,这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意这里指定的文件名不可以包含…

AE基础知识

一、基础概念 1.AE的用途(合成) AE是一款用于高端视频特效系统的专业特效合成软件,通过对收集到的素材进行数字化的编辑组合到一起,进行艺术性的再加工后得到的最终作品。 2.帧 帧——就是影像动画中最小单位的单幅影像画面&a…

FPGA XDMA 中断模式实现 PCIE3.0 AD7606采集 提供2套工程源码和QT上位机源码

目录 1、前言2、我已有的PCIE方案3、PCIE理论4、总体设计思路和方案AD7606数据采集和缓存XDMA简介XDMA中断模式QT上位机及其源码 5、vivado工程1--BRAM缓存6、vivado工程2--DDR4缓存7、上板调试验证8、福利:工程代码的获取 1、前言 PCIE(PCI Express&am…

设计模式什么情况下适合使用呢?

很多情况下设计模式是一种经过验证的解决特定问题的最佳实践。设计模式提供了一种标准化的方式来解决常见的软件设计问题,并提供了一种可重用的解决方案。设计模式可以帮助开发人员编写具有高可维护性、可扩展性和可重用性的代码。 设计模式适用于以下情况&#xf…

redis之Bitmap

位图数据结构其实并不是一个全新的玩意,我们可以简单的认为就是个数组,只是里面的内容只能为0或1而已(二进制位数组)。 GETBIT用于返回位数组在偏移量上的二进制位的值。值得我们注意的是,GETBIT的时间复杂度是O(1)。 GETBIT命令的执行过程如…

Ubuntu系统adb开发调试问题记录

Ubuntu系统adb开发调试问题记录 一、adb devices no permissions二、自定义adb server端口三、动态库目录四、USB抓包 一、adb devices no permissions lsusb -t 设备树直观地查看设备的Bus ID和Device Num,lsusb找到对应的PID和VID编辑udev规则 sudo vim /etc/ud…

百度文心千帆大模型平台:企业级大模型服务的新航标

随着人工智能和大数据的快速发展,大模型平台正越来越受到各大企业和个人开发者的青睐。本文将以百度最新推出的文心千帆大模型平台为例,深入分析其在国家战略布局,经济发展趋势,市场变化动向和技术研发周期等方面的影响和应用。同…

JavaScript--Promise类

在学习Promise类内容前,你需要先了解什么是异步编程,可以参考JavaScript--异步编程,JavaScript--定时事件 Promise介绍: Promise是JavaScript中用于处理异步操作的对象。它代表着一个异步操作的最终完成(或失败)以及…

matplotlib从起点出发(6)_Tutorial_6_Animations

1 在matplotlib中使用动画 基于其绘图功能,matplotlib还提供了一个使用动画模块生成动画animation的接口。动画是一系列帧,其中每个帧对应于图形Figure 上的一个绘图。本教程介绍了有关如何创建此类动画的一般准则以及可用的不同选项。 import matplot…

php 服务器 http状态码为499的解决办法

原因:某些http请求服务端处理太慢,影响了其他http请求。 1.配置php.ini的max_execution_time和max_input_time。但是改后还是报了不少的499。 (set_time_limit()函数和配置指令max_execution_time只影响脚本本身执行的时间。任何发生在诸如…

行为型设计模式之观察者模式【设计模式系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everythi…

解决报错Avoid using non-primitive value as key, use string/number value instead.

找到图中画圈的文件这个错误信息的意思是要避免使用非基本值作为键&#xff0c;而是使用字符串/数字值代替。 [1] 这个错误通常出现在使用<el-select>中的<el-option>进行循环遍历值时。 [2] 这个错误的解决方案是检查是否有重复的键值&#xff0c;并确保使用字符…

【Python】aio Queue 的超时封装

一般封装生产者消费者模型的时候会用到 asyncio.Queue&#xff0c;queue 的 put 和 get 操作都是阻塞的&#xff08;当然可以通过 _nowait 方法改为非阻塞&#xff09;&#xff0c;取数据的时候如果没数据则会一直阻塞。下面通过计数的方法给 asyncio.Queue 添加超时操作&#…

从源码编译 tensorFlow ,启用CPU 指令加速

适合只有cpu,没有显卡的AI 玩家&#xff0c;初学者 问题&#xff1a;AVX AVX2 AVX_VNNI FMA 是什么? AVX、AVX2、AVX_VNNI 和 FMA 都是针对 Intel CPU 的特殊指令集&#xff08;instruction set&#xff09;&#xff0c;用于加速数值计算和向量化操作。这些指令集提供了高级…

【分布鲁棒、状态估计】分布式鲁棒优化电力系统状态估计研究[几种算法进行比较](Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

基于BIM+AI的建筑能源优化模型【神经网络】

推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 AEC&#xff08;建筑、工程、施工&#xff09;行业的BIM 技术&#xff0c;允许在实际施工开始之前虚拟地建造建筑物&#xff1b; 这带来了许多有形和无形的好处&#xff1a;减少成本超支、更有效的协调、增强决策权等等。…

C#实现数据库数据变化监测(sqlservermysql)

监测数据库表数据变化&#xff0c;可实现数据库同步&#xff08;一主一从&#xff08;双机备份&#xff09;&#xff0c;一主多从&#xff08;总部数据库&#xff0c;工厂1&#xff0c;工厂2&#xff0c;工厂数据合并到总部数据&#xff09;&#xff09; sqlserver 启用数据库…

Flowable-服务-消息任务

文章目录 定义图形标记XML内容集成Rabbitmq引入pom包配置rabbitmq 操作界面 定义 Mq 任务不是 BPMN 2.0 规范定义的官方任务&#xff0c;在 Flowable 中&#xff0c;Mq 任务是作为一种特殊的服务 任务来实现的&#xff0c;主要做Mq消息发送。 图形标记 由于 Mq 任务不是 BPM…

用CSS和HTML写一个水果库存静态页面

HTML代码&#xff1a; <!DOCTYPE html> <html> <head><link rel"stylesheet" type"text/css" href"styles.css"> </head> <body><header><h1>水果库存</h1></header><table>…