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

news/2024/5/17 19:28:38

文章目录

  • 一、设计模式
    • 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.mrgr.cn/p/60538470

相关文章

linux 安装FTP

检查是否已经安装 $] rpm -qa |grep vsftpd vsftpd-3.0.2-29.el7_9.x86_64出现 vsftpd 信息表示已经安装,无需再次安装 yum安装 $] yum -y install vsftpd此命令需要root执行或有sudo权限的账号执行 /etc/vsftpd 目录 ftpusers # 禁用账号列表 user_list # 账号列…

认识 springboot 之 它的配置文件 -2

前言 本篇了解springboot中配置的作用,介绍配置文件的种类,介绍简单使用配置文件,简单的小技巧如何设置注释,开启热部署等等,如有错误,请在评论区指正,让我们一起交流,共同进步&…

HBase有写入数据,页面端显示无数据量

写了一个测试类,插入几条数据,测试HBase的数据量。很简单的功能,这就出现问题了。。网页端可以看到,能够看到读写请求,但是不管是内存、还是磁盘,都没有数据。 于是就想到去HDFS查看,也是有数据…

RBAC三级树状菜单实现(从前端到后端)未完待续

1、表格设计 RBAC 2、前端路由 根据不同的用户id显示不同的菜单。 根据路由 3、多级菜单 展示所有权限,并且根据当前用户id展示它所属的角色的所有菜单。 前端树状展示 思路: 后端:传给前端map,map里1个是所有菜单&am…

Ubuntu Server版 之 apache系列 安装、重启、开启,版本查看

安装之前首先要检测是否安装过 apt list --installed | grep tool tool:要检测的名称,如mysql、apache 、ngnix 等 安装 apache sudo apt install apache2 安装apache 默认是开启的 可以通过浏览器 检测一下 service apache stop # apache 停止服务…

解决路由缓存问题

产生原因 路由只有参数发生变化时 会复用组件实例 解决 1.选择key 简单粗暴 2.选择beforeRouteUpdate钩子函数

Mybatis初识(一)

一.Mybatis是什么 MyBatis 是一款优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射。MyBatis 去除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的XML或注解来配置,和映射原始类型、接口和Java POJO (Plain Old Java Objects…

使用CRM分析数据有哪些功能?

CRM数据分析软件可以帮助企业增强竞争力,并更好地了解客户需求及市场变化,助力企业数据分析,并提供实时更新的数据和分析结果,CRM数据分析软件的主要特点是什么?包括以下6个特点。 CRM数据分析软件的主要功能通常包括…

java数组对象初始化分析

分析代码 public static void main(String[] args) {int a10,b20,c30,d 40,e 50,f60;int aa[] {a,b,c,d,e,f};aa[2] 100;}代码的字节码 图解分析 refs https://docs.oracle.com/javase/specs/jvms/se19/html/jvms-6.html#jvms-6.5.aloadhttps://docs.oracle.com/javase/sp…

pve安装ikuai并设置,同时把pve的网络连接到ikuai虚拟机

目录 前因 前置条件 安装ikuai 进入ikuai的后台 配置lan口,以及wan口 配置lan口桥接 按实际情况来设置了 单拨(PPOE拨号) 多拨(内外网设置点击基于物理网卡的混合模式) 后续步骤 pve连接虚拟机ikuai的网络以及其他虚拟机连接ikuai的网…

Linux NUMA架构(非统一内存访问)

NUMA架构 NUMA Architecture| Non Uniform Memory Access Policy/Model | Numa Node Configuration (CPU Affinity) NUMA架构产生的原因 cpu的高速处理功能和内存存储直接的速度会严重影响cpu的性能。传统的计算机单核架构,cpu通过内存总线(内存访问控制器)直接连接到一…

哈工大计算机网络课程网络安全基本原理之:身份认证

哈工大计算机网络课程网络安全基本原理之:身份认证 在日常生活中,在很多场景下我们都需要对当前身份做认证,比如使用密码、人脸识别、指纹识别等,这些都是身份认证的常用方式。本节介绍的身份认证,是在计算机网络安全…

微信小程序使用ECharts的示例详解

目录 安装 ECharts 组件使用 ECharts 组件图表延迟加载 echarts-for-weixin 是 ECharts 官方维护的一个开源项目,提供了一个微信小程序组件(Component),我们可以通过这个组件在微信小程序中使用 ECharts 绘制图表。 echarts-fo…

Ubuntu Server版 之 共享文件 samba和NFS 两种方法

NFS 和 Samba NFS : linux之间资源共享 Samba: 是windows系统与Linux系统之间资源共享的 samba 安装samba 工具 sudo apt install samba 创建共享目录 sudo mkdir /home/shared sudo chmod 777 /home/shared 配置sambd sudo vim /etc/samba/smb.con…

vue - 【完整源码】实现评论区发表评论、回复评论、评论盖楼等功能,前端PC网站/移动端H5实现多用户评论与回复功能(详细示例源码,一键复制开箱即用)

效果图 在vue项目开发中,实现一个类似社交软件的评论区发表留言及回复等评论功能效果,可以无限回复盖楼。 一、功

Python - OpenCV识别条形码、二维码(已封装,拿来即用)

此代码可识别条形码和二维码,已封装好,拿来即用: import cv2 import pyzbar.pyzbar as pyzbar import numpy from PIL import Image, ImageDraw, ImageFontclass CodeScan():def __init__(self):super(CodeScan, self).__init__()def decode…

【C++】继承

文章目录 一.继承的概念及定义二.继承方式与访问限定符三.基类和派生类对象赋值转换四.继承中的作用域五.子类的默认成员函数六.继承和友元、静态成员的关系七.菱形继承和菱形虚拟继承1.菱形继承所引发的问题(1)二义性(1)数据冗余…

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服务器是一个应用程序(软件&…

01 Excel常用高频快捷键汇总

目录 一、简介二、快捷键介绍2.1 常用基本快捷键1 复制:CtrlC2 粘贴:CtrlV3 剪切:CtrlX4 撤销:CtrlZ5 全选:CtrlA 2.2 常用高级快捷键1 单元格内强制换行:AltEnter2 批量输入相同的内容:CtrlEnt…

自动化运维工具——Ansible

自动化运维工具——Ansible 一、Ansible概述二、ansible 环境安装部署1.管理端安装 ansible2.ansible 目录结构3.配置主机清单4.配置密钥对验证 三、ansible 命令行模块1.command 模块2.shell 模块3.cron 模块4.user 模块5.group 模块6.copy 模块7.file 模块8.hostname 模块9&a…