C++(week14): C++提高:(一)面向对象设计:设计原则、设计模式

文章目录

  • 一、面向对象设计的概念
    • 4.统一建模语言:UML语言
      • StartUML
  • 二、类与类之间的关系
    • 0.总结
    • 1.继承 (泛化耦合)
    • 2.组合 (Composition)
    • 3.聚合 (Aggregation)
    • 4.关联
      • (1)双向关联
      • (2)单向关联
    • 5.依赖 (Dependency)
  • 三、面向对象设计的原则
    • 0.总结
    • 1.单一职责原则 (Single Responsibility Principle)
    • 2.开放-闭合原则(Open Closed Principle)
    • 3.里氏替换原则 (Liscov Substitution Principle)
    • 4.接口分离原则 (Interface Segregation Principle)
    • 5.依赖倒置原则 (Dependency Inversion Principle)
    • 6.迪米特法则/最少知识原则(Law of Demeter -> Least Knowledge Principle)
    • 7.组合复用原则 (Composite/Aggregate Reuse Principle)
  • 四、设计模式
    • (一)创建型模式
      • 1.单例模式
      • 工厂模式
      • 2.简单工厂模式
      • 3.工厂方法模式
      • 4.抽象工厂模式
    • (二)结构型模式
      • 1.代理模式
    • (三)行为型模式
      • 1.观察者模式
    • (四)其他非23种经典模式的设计模式
      • 1.Pimpl模式
      • 2.Reactor模式
      • 3.Preactor模式

一、面向对象设计的概念

1.面向对象的分析 (OOA):分析出要做什么,将需要展示出来。
2.面向对象的设计 (OOD):把类、类中的数据成员与成员函数设计出来,类与类之间的关系。
3.面向对象的编程 (OOP):将面向对象设计中的类、数据成员、成员函数实现出来。
在这里插入图片描述

4.统一建模语言:UML语言

StartUML

在这里插入图片描述

+:public
#:protected
-:private

①画图解决不了的,用右边栏的属性(Properities)
②静态:static:下划线
③纯虚函数/抽象类:is abstract:斜体
④const、std:::写不了,不写了
⑤继承:默认是公有继承



二、类与类之间的关系

0.总结

一、类与类的五种关系
1.继承:继承语法,强耦合
2.组合:使用成员子对象。有整体-部分的关系。整体负责局部的销毁。部分不能独立于整体存在。
3.聚合:有整体-部分的关系。整体不负责局部的销毁。部分可以独立于整体存在。
4.关联:拥有对方的指针,作为数据成员
5.依赖:只是临时使用,并不拥有


二、区别
1.方向:继承关系是一个纵向关系,其他四种是水平关系。
2.从语义层面来看:继承关系是is、依赖关系是use、关联、组合、聚合是has
3.耦合程度:继承 > 组合 > 聚合 > 关联 > 依赖
4.继承:既强调数据成员,又强调成员函数
组合、聚合、关联:强调两个类的数据成员的关系
依赖:强调的是两个类的成员函数的关系

之前我们实现多态使用的是继承与虚函数这种面向对象的方法。现在知道了类与类之间的其他关系后,可以使用组合与依赖这种基于对象的方法实现。


在这里插入图片描述
上图展示了几种耦合的示例。其中汽车和交通工具属于泛化耦合,轮子和方向盘组合于汽车,汽车聚合成车队,而汽车和司机具有依赖关系。


1.继承 (泛化耦合)

1.基类与派生类,基类部分会成为派生类的一部分。
可以吸收,但是不一定能访问。比如基类的private成员,派生类会吸收,但因为私有,没有访问权限。

2.类图的画法:派生类指向基类的空心三角箭头。

3.语义层面:B is A,B继承A,经理是一个员工。

4.泛化:
在这里插入图片描述
继承:先有基类,然后派生出新的类,也就是派生类。
泛化(一般化):先有派生类,然后将具体相同属性抽象出来,然后形成了基类。

5.类图
在这里插入图片描述


2.组合 (Composition)

表示整体与部分的关系,部分不能独立于整体存在整体负责部分的生命周期


组合(Composition):一种强的拥有关系,体现了严格的部分和整体的关系,部分和整体具有一样的生命周期。

①是一种最强的关联关系,表现为整体与局部的关系,整体负责局部对象的销毁
②在语义层面上:A has B。
③在代码层面上表现为:数据成员以成员子对象的形式存在。
④在类图的画法上:从局部指向整体实心菱形箭头
⑤如:主公司和子部门、人体与各个器官。

在这里插入图片描述


3.聚合 (Aggregation)

表示整体与部分的关系,但部分可以独立于整体存在整体不负责局部对象的销毁


聚合(Aggregation):一种弱的拥有关系,体现A对象可以包含B对象,但B对象不是A对象的一部分。

①聚合是一种稍微强一点的关联关系,表现为整体与局部的关系。但是整体不负责局部对象的销毁
②语义层面:A has B
③代码层面:使用的是指针或引用
④类图的画法上:从局部指向整体空心菱形箭头

在这里插入图片描述


4.关联

(1)双向关联

彼此知道对方的存在,但是彼此并不负责对方的生命周期。
①在语义层面上: A has B
②在代码层面上:使用的是指针或引用
③在类图的画图上:使用的是实心实线
在这里插入图片描述
在这里插入图片描述


(2)单向关联

1.定义
一个类知道另一个类,并且可以通过指针或引用访问另一个类的对象。彼此不负责对方的生命周期。没有整体与部分的概念。
①A类知道B类的存在,B类却不知道A类的存在。
A类拥有B类的指针或引用作为A类的数据成员,可以通过这个指针或引用访问B类的对象。长久持有,而不是临时使用。(临时使用的传参是依赖)
②在语义层面上:A has B
③类图画法上:A指向B的实线箭头

2.实现:
一个类包含指向另一个类的指针或引用。

3.举例:
Person类中包含指向Vehicle类的指针(Vehicle *_vehicle),Person类可以调用Vehicle类的run方法,但并不负责Vehicle对象的生命周期管理。

在这里插入图片描述

在这里插入图片描述


5.依赖 (Dependency)

依赖(Dependency):由于逻辑上相互协作可能,而形成的一种关系。

A use B
虚线箭头

B临时的传参给A,作为A的成员函数的参数,则A依赖B
在这里插入图片描述

是两个类之间的一种不确定的关系,语义上是一种A use B的关系,这种关系是偶然的,临时的,并非固定的。在类图的画法上:使用虚线的箭头,从A指向B。在代码上表现为:
①B作为A的成员函数参数;
②B作为A的成员函数的局部变量(B作为A的成员函数的返回值);
③A的成员函数调用B的静态方法。

在这里插入图片描述



三、面向对象设计的原则

0.总结

一个优良的系统设计,遵循的要求:低耦合、高内聚
①耦合:强调的是类与类之间、模块与模块之间的关联的程度。
②内聚:强调的是类内部、模块内部的关系。

低耦合:类与类之间关系弱。当一个类发生改变时,另一个类不会受到太大的影响。
高内聚:一个类尽量只做一件事。

1.单一职责原则:一个类只负责一件事。功能分离。
2.开放闭合原则(OCP):对扩展开放,对修改关闭。
3.里氏替换原则(LSP):子类要能完全地替代父类。
4.接口分离原则:要按需提供小接口,不要提供肥大的接口,用不到的功能接口就不要提供
5.依赖倒置原则:高层模块不应该依赖于底层,即抽象不应该依赖细节,细节应依赖抽象。
6.最少知识原则:一个对象应该尽可能少地了解其他的对象,即一个对象只应与它直接关联的对象进行交互。例如,Driver 类只知道 Car 类,而不知道 Engine 类的存在。Driver 通过 Car 类的接口启动汽车,而不是直接访问 Engine 类。
7.组合复用原则:优先使用对象的组合而不是继承来实现功能的复用。将功能分解为独立的组件,然后将这些组件组合起来,实现灵活和可扩展的系统设计。


在这里插入图片描述
在这里插入图片描述


1.单一职责原则 (Single Responsibility Principle)

核心思想:一个类(模块),最好只做一件事,引起它变化的原因只有一个。
核心是:解耦与增加内聚性。

举例:
在这里插入图片描述

计算功能,只需要area(),就把draw()方法抽离出来,单独封装一个类。把一个大的类拆开。
在这里插入图片描述


2.开放-闭合原则(Open Closed Principle)

对扩展开放,对修改关闭。

核心思想:对抽象编程,而不对具体编程,因为抽象相对稳定。

在这里插入图片描述


举例:原本的设计,如果要添加功能,例如要求幂和开方。需要修改源代码。真正编程的时候,如果一个大的基类被修改,所有继承它的派生类都会受到影响,可能会造成意想不到的错误。

(1)若没有遵循开闭原则,所有功能都做在计算器类中。则后来的人新增功能,需要对前人写的老代码进行修改,改动别人的代码,有可能会造成问题。
(2)遵循开闭原则,将每个功能分离到一个类中。这样新增一个功能,只需要新写一个类。而不需要去改动之前的老代码。新增的模块出现问题,也好定位。

在这里插入图片描述

修改后:基类是抽象类,只做一个接口。具体实现交给派生类。能很好地应对变化和扩展。只需要新加类,而不需要修改哪个类的源代码,尤其是对基类的修改。
在这里插入图片描述


3.里氏替换原则 (Liscov Substitution Principle)

子类要能完全地替代父类。

里氏代换原则表明,在软件中将一个基类对象替换成它的派生类对象,程序将不会产生任何错误和异常,反过来则不成立。【派生类不能有隐藏,不能与基类有同名的(非虚)函数。增加自己的个性要用新的函数名】

核心思想:派生类必须能够替换其基类。派生类可以扩展基类的功能,但不能改变基类原有的功能。表现为:①派生类(子类)可以实现基类(父类)的抽象方法,表现多态,但不能隐藏基类(父类)的非抽象方法。②派生类(子类)可以有自己的个性,即派生类可以增加自己的新的方法、属性。


4.接口分离原则 (Interface Segregation Principle)

定义:客户端不应该依赖那些它不需要的接口。
核心思想:使用多个小的专门的接口,而不要使用一个大的总接口。


举例:Bird实现的功能太多了,而鸵鸟并不满足
在这里插入图片描述

Bird类默认是不会飞的鸟,鸵鸟来继承不会飞的鸟。
分离出fly(),形成会飞的鸟FlyingBird,乌鸦来继承会飞的鸟。
在这里插入图片描述
①这里看起来没有满足单一职责原则。所以实际写代码,并不一定要完美遵循所有的设计原则,否则会导致类的数量过多。
②若是以后要添加不能在陆地上行走walk()的鸟类,则这时候就必须修改框架里的基类,会违反开放闭合原则,但也没有办法,因为这是当初设计的时候有问题。
所以,在设计最初的基类时,功能既不能设计太少(满足单一职责原则,但类会过多),也不能设计太多(若子类有不需要的功能,违反接口分离原则。若要修改原本的基类,违反开放闭合原则),要酌情折中。


5.依赖倒置原则 (Dependency Inversion Principle)

定义:高层模块不应该依赖低层模块,它们都应该依赖抽象。抽象不应该依赖于细节,细节应该依
赖于抽象。简单来说,依赖倒置原则要求针对接口编程,不要针对实现编程。

核心思想:面向接口编程,依赖于抽象。面向抽象编程

在大多数情况下,开闭原则、里氏代换原则和依赖倒置原则会同时出现,开闭原则是目标,里氏替换原则是基础,依赖倒置原则是手段。


举例:
在这里插入图片描述
修改后:设计为抽象类。添加新的需求,不改变老的框架。
在这里插入图片描述


6.迪米特法则/最少知识原则(Law of Demeter -> Least Knowledge Principle)

定义:每一个软件单位对其他单位都只有最少的知识,而且局限于那些与本单位密切相关的软件单
位。
迪米特法则要求一个软件实体应当尽可能少地与其他实体发生相互作用。如果一个系统符合迪米特
法则,那么当其中的某一个模块发生修改时就会尽量少地影响其他模块,扩展会相对容易,这是对软件实体之间通信的限制,迪米特法则要求限制软件实体之间通信的宽度和深度。应用迪米特法则可降低系统的耦合度,使类与类之间保持松散的耦合关系。当两个类之间直接通信的时候,会造成高度依赖的后果(高耦合)。解决此问题的办法,尽量避免两个类直接接触(低耦合),通过一个第三者做转发。

最少知识原则:专业的事情,交给专业的人。用最少的知识解决问题。

举例1:A方案,购房者需要了解所有的楼盘。B方案,购房者找房产中介,降低了购房者与楼盘的耦合度。
在这里插入图片描述

举例2:设计模式之Pimpl模式
Line类中原本是嵌套实现了Point类。现在Line中只放LinePimpl*,在LinePimpl类中存放Point类的具体实现。这样Point类的变化不会影响到Line类,降低了模块之间的耦合程度。并且对Line类屏蔽了Point类的内部实现。

看看pfd:6.2类域.pdf


7.组合复用原则 (Composite/Aggregate Reuse Principle)

核心思想:复用时要尽量使用组合/聚合关系(关联关系),少用继承。即降低耦合程度。

举例:人继承车,不太合适。车发生了变化,人就会继承这种变化,耦合程度过于强了。
在这里插入图片描述

修改后:人类只用了车类的指针,单向关联。
在这里插入图片描述

OO真经:程序世界与实现世界中依赖的区别
在这里插入图片描述

程序世界中对象间的依赖是以类为单位的,这种依赖关系会随着泛化过程而被泛化到类里面去。并且,只要两个类建立了依赖,那么两个类之间的所有对象都两两依赖了。换句话说,在程序世界里,只要有一个“人”和一个“大学”发生了联系,那么这种联系就被泛化到类中了,随后,所有的“人”都可以上“任何”的大学。



四、设计模式

设计模式:它是解决特定问题的一系列套路,有一定的普遍性。它可以提高代码的可重用性、可读性、可靠性、可扩展性。


(一)创建型模式

创建型模式 (Creational patterns) 有5种
提供对象创建机制,增加现有代码的灵活性和重用。

在这里插入图片描述

1.单例模式

全局区域只有一个类的实例。

之前在三篇中讨论过。后续有时间会合并一下。

1.C++(week10):C++基础: 第二章 类与对象
2.设计模式
3.单例模式


工厂模式

1.简单工厂:有一个工厂类,里面每个成员函数对应生产一种产品
2.工厂方法:有一个抽象工厂类,下面派生各个具体产品的工厂。每一个产品对应一个工厂,即一个工厂仅能生产一个具体的产品。
3.抽象工厂:有一个抽象工厂类,成员函数是各个品牌。派生类是所有品牌对应的产品系列。新增一个系列很容易,但(不修改抽象工厂类的话)无法新增品牌。每个具体工厂可以生产所有品牌对应的该系列产品。每个具体工厂类负责生产一系列相关或相互依赖的产品。


2.简单工厂模式

1.定义
简单工厂模式(静态工厂方法模式):
①工厂会根据产品的名字生产出对应的产品。
②一个工厂可以生产出多个产品。
③简单工厂模式提供了专门的工厂类用于创建对象,实现了对象创建和使用的分离。

2.优点
只需要知道产品的名字就可以生产出对应的产品。

3.缺点
违反了设计原则:单一职责原则 (工厂的功能过于复杂)、开放闭合原则(增加新产品需要修改工厂源代码)、依赖倒置原则 (面向抽象编程,而不是面向具体编程)

4.类图
在这里插入图片描述

在这里插入图片描述

5.代码链接:https://github.com/WangEdward1027/DesignPatterns/blob/main/Factory/simpleFactory2.cpp


3.工厂方法模式

1.定义
工厂类作为抽象类,每一个产品对应一个派生类工厂。

2.优点
①满足了单一职责原则、开放闭合原则、依赖倒置原则
②新增代码时,只需要在Figure类和Factory类下分别派生梯形类,然后依赖。不需要修改源代码。

3.缺点
工厂的数量会随着产品数量的增加而增加

4.类图
在这里插入图片描述

5.代码链接:https://github.com/WangEdward1027/DesignPatterns/blob/main/Factory/factoryMethod.cpp


4.抽象工厂模式

1.定义

2.优点
①抽象工厂,减少了工厂的数量。
②可以对一类品牌的产品进行细分
③每个工厂类可以生产产品族

3.缺点
不修改源代码,无法生产新类型品牌。只能在已有品牌上进行新系列产品的扩展。

4.类图
不适合新的品牌,但时候老品牌出新的产品系列。

两个品牌,下属两个产品。
在这里插入图片描述

三个品牌,下属三个产品。
在这里插入图片描述

在这里插入图片描述



(二)结构型模式

结构型模式(Structural patterns)有7种
解释如何将对象和类组装成更大的结构,同时保持结构的灵活性和高效性。

在这里插入图片描述

1.代理模式

string写时复制COW,不能分开读和写,就用charProxy。

C++(week11): C++基础 第五章: 运算符重载、友元



(三)行为型模式

行为型模式(Behavioral patterns)11种
负责有效的沟通和对象之间的责任分配。
在这里插入图片描述

1.观察者模式

1.概念
观察者模式(Observer Pattern)是一种行为型设计模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。当这个主题对象的状态发生变化时,所有依赖于它的对象都会收到通知并自动更新。这个模式常用于实现事件处理系统。


2.观察者模式的结构
观察者模式涉及到四个主要角色:
(1)主题(Subject):维护观察者列表,提供方法来增加和移除观察者,并在状态发生变化时通知所有观察者。
(2)具体主题(Concrete Subject):具体的主题类,维护具体的状态,并在状态变化时通知观察者。
(3)观察者(Observer):定义了一个更新接口,用于接收主题通知。
(4)具体观察者(Concrete Observer):实现观察者接口,定义如何响应主题的更新


3.观察者模式的主要特点
(1)松耦合:主题(Subject)和观察者(Observer)之间的耦合度很低。主题只知道观察者实现了某个接口,而不知道具体的实现细节。这使得主题和观察者可以独立地扩展和修改。
(2)动态观察者列表:观察者可以在运行时动态地加入或退出,灵活性高。
(3)广播通信:主题对象状态发生变化时,会通知所有注册的观察者,实现了一种广播通信机制。
(4)支持事件驱动模型:观察者模式适合用于需要事件通知机制的系统,如GUI应用程序中的事件处理、消息系统等。


4.实现
(1)所有关注者(attach)的,在主题更新后会得到通知(notify)。观察者会被用list链表保存。若不想被通知,则可以取消关注(detach)。
(2)定义对象的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
当一个对象发生了变化,关注它的对象就会得到通知;这种交互也称为发布-订阅(publish-subscribe)。


4.类图
在这里插入图片描述

5.代码链接:https://github.com/WangEdward1027/DesignPatterns/blob/main/Observer/Observer.cpp



(四)其他非23种经典模式的设计模式

1.Pimpl模式

C++(week11): C++基础 第五章: 运算符重载、友元


2.Reactor模式

后续C++线程池补充


3.Preactor模式

后续C++线程池补充

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

你还以为前端无法操作文件吗

🧑‍💻 写在开头 点赞 收藏 学会🤣🤣🤣 这里面有个值得说明一点的问题是,我一直以为(可能有人跟我一样)前端是无法操作文件的,可实际上自从HTML5标准出现之后&#xff…

昇思25天学习打卡营第21天|CV-Shufflenet图像分类

打卡 目录 打卡 ShuffleNet 网络介绍 ShuffleNet 模型架构 Pointwise Group Convolution Channel Shuffle ShuffleNet模块 ShuffleNet 模块代码 构建ShuffleNet网络 模块代码 模型训练和评估 模型训练 模型评估 模型预测 ShuffleNet 网络介绍 ShuffleNetV1是旷视科…

数字图像处理笔记(三) ---- 傅里叶变换的基本原理

系列文章目录 数字图像处理笔记(一)---- 图像数字化与显示 数字图像处理笔记(二)---- 像素加图像统计特征 数字图像处理笔记(三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、傅里叶变换二、离散傅里叶变…

JCR一区级 | Matlab实现TTAO-Transformer-LSTM多变量回归预测

JCR一区级 | Matlab实现TTAO-Transformer-LSTM多变量回归预测 目录 JCR一区级 | Matlab实现TTAO-Transformer-LSTM多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.【JCR一区级】Matlab实现TTAO-Transformer-LSTM多变量回归预测,三角拓扑聚合…

【运维自动化-配置平台】模型及模型关联最小化实践

蓝鲸智云配置平台,以下简称配置平台 我们知道主机是配置平台最常见的管控资源对象,在业务拓扑里可以通过划分模块来清晰的可视化管理;那其他资源如何通过配置平台来纳管呢,比如网络设备交换机。场景需求:如何把交换机…

【Linux 驱动】IMX6ULL eLCDIF参考手册翻译

1. eLCDIF 1.1 概述 eLCDIF是一种通用的显示控制器,用于驱动各种尺寸和性能不同的显示设备。 eLCDIF块支持以下功能: 支持MPU接口(8080模式和6800模式)支持DOTCLK接口(RGB接口)VSYNC模式:针对高…

Maven高级——详解

目录 一、分模块设计 二、分模块设计小实践 三、Maven继承 1.继承关系实现 ​编辑 2.版本锁定 dependencyManagement 自定义属性/引用属性 四、Maven聚合 五、Maven私服 一、分模块设计 为什么要分模块设计,将项目按照功能拆分分成若干个子模…

QT串口和数据库通信

创建串口 串口连接客户端并向服务器发送消息 client.pro #------------------------------------------------- # # Project created by QtCreator 2024-07-02T14:11:20 # #-------------------------------------------------QT core gui network QT core gui…

房屋出租系统 学习笔记 韩顺平 零基础30天学会Java(2024.7.15)

代码见package houserent P362 房屋出租需求 P363 房屋出租设计 分层模式 P364 房屋出租工具 给了一个工具包:Utility,使用:String s2 Utility.readString(10,”hspedu”);来限制输入字符大小最大是10,同时初始化的值为hspedu&a…

完全移动huggingface模型仓库(不是简单mv)

Linux中移动huggingface模型仓库 参考链接 先在bashrc中配置: export HF_DATASETS_CACHE"/your/path/dataset" export HF_HOME"/your/path/" export HUGGINGFACE_HUB_CACHE"/your/path/hub" export TRANSFORMERS_CACHE"/your…

速腾聚创激光雷达复现FAST-LIO

目录 1.软件环境 2.测试执行 3.代码学习 3.1.找主节点代码文件 3.2.整体流程结构 3.3.具体函数理解 记录复现FAST-LIO算法的过程和,代码梳理和理解 1.软件环境 Windows 10(64bits) VMware 16 Pro Ubuntu 20.04 ROS Noetic FAST-LIO的简化版、注释版。感谢…

Hospital 14.6.0全开源医院管理预约系统源码

InfyHMS 具有 60 种功能和 9 种不同类型的用户类型, 他们可以登录系统并根据他们的角色访问他们的数据。 源码下载:https://download.csdn.net/download/m0_66047725/89580674 更多资源下载:关注我。

Top-down Microarchitecture Analysis Method

1、英文链接: 1. https://www.intel.com/content/www/us/en/docs/vtune-profiler/cookbook/2023-0/top-down-microarchitecture-analysis-method.html 2. http://portal.nacad.ufrj.br/online/intel/vtune2017/help/GUID-02271361-CCD4-410C-8338-4B8158157EB6.ht…

LC61----1374. 生成每种字符都是奇数个的字符串(字符串)---java版

1.题目 2.思路 (1)题目要生成每种字符是奇数个的字符串。 (2)所以直接用参数n%2来判断。 (3)返回的字符串必须只含小写英文字母。如果存在多个满足题目要求的字符串,则返回其中任意一个即可。 (4)感觉题目不是很规范哈…

go程序在windows服务中优雅开启和关闭

本篇主要是讲述一个go程序,如何在windows服务中优雅开启和关闭,废话不多说,开搞!!!   使用方式:go程序 net服务启动 Ⅰ 开篇不利 Windows go进程编译后,为一个.exe文件,直接执行即…

知名医药医疗行业人工智能数字化转型讲师培训师唐兴通谈医药医疗销售与创新思维创新管理数字化AI及大客户销售医美生活美容品牌市场

​唐兴通 数字化商业创新顾问、数字化转型教练、沃顿商学院演讲嘉宾。全球商业思想大家EM罗杰斯(创新的扩散)、杰弗里摩尔(跨越鸿沟)、马修狄克逊(挑战式销售)、布兰登博格(竞合战略&#xff0…

css渐变色背景|<gradient

使用渐变色作为背景 可以直接将渐变色用作元素的背景&#xff0c;可以看做是一种特殊的背景图片。&#xff08;是作为背景background一个属性值不是背景颜色background-color的属性值 &#xff09; CSS 渐变是一种从一种颜色平滑过渡到另一种颜色的效果&#xff0c;由 <gra…

Java数据结构(四)——链表

文章目录 链表概念及结构单链表的实现LinkedList的使用构造方法遍历 LinkedList的模拟实现ArrayList与LinkedList区别链表的相关练习反转链表链表的中间结点链表的回文结构判断链表是否有环寻找入环的第一个结点 链表 概念及结构 链表是一种物理存储结构上非连续存储结构&…

【C语言】 二叉树创建(结构体,先序遍历,中序遍历,后续遍历)

二叉树的创建&#xff1a;首先先定义一个结构体&#xff0c;里面包含数据&#xff08;data&#xff09;&#xff0c;指向左子树的指针&#xff08;L&#xff09;&#xff0c;指向右子树的指针&#xff08;R&#xff09;三个部分 在创建树的函数中&#xff0c;首先先输入…

netty使用redis发布订阅实现消息推送

netty使用redis发布订阅实现消息推送 场景 项目中需要给用户推送消息: 接口 RestController public class PushApi {Autowiredprivate PushService pushService;/*** 消息推送* param query* return*/PostMapping("/push/message")public String push(RequestBody…