读书笔记:C++20设计模式

C++20设计模式:可复用的面向对象设计方法:reusable approaches for object-oriented software design,second edition (俄)德米特里·内斯特鲁克(Dmitri Nesteruk)著 , 冯强国译

译者序

你需要有C++基础,了解C++新特性(lambda,auto,override)

第1章 引论1

《设计模式:可复用面向对象软件的基础》ISBN 978-7-111-61833-1就是以c++和smalltalk语言作为例程。
1.1 本书的目标读者2
1.2 关于代码示例2
1.3 关于开发者工具3

1.4 重要概念3

继承

struct MyClass : SomeBase<MyClass>

1.4.1 奇异递归模板模式3
1.4.2 Mixin继承4
1.4.3 旧风格的静态多态5
1.4.4 概念与静态多态6
1.4.5 属性7

1.5 SOLID设计原则8

  • 单一职责原则(Single Responsibility Principle, SRP)
  • 开闭原则(Open-Closed Principle, OCP)
  • 里氏替换原则(Liskov Substitution Principle, LSP)
  • 接口隔离原则(Interface Segregation Principle, ISP)
  • 依赖倒转原则(Dependency Inversion Principle, DIP)

1.5.1 单一职责原则8

每个类只有一个职责,因此也只有一个修改该类的原因。即只有该职责变化时,该类才做相应的修改。

1.5.2 开闭原则10

我们不必返回到已经编写和测试的代码来修改它。

1.5.3 里氏替换原则15

如果某个接口以基类Parent类型的对象为参数,那么它应该同等地接受子类Child类对象作为参数,并且程序不会产生任何异常。

正方形继承长方形

class Square:public Rectangle
{}// 接口以Parent作为参数
void process(Rectangle& r)

1.5.4 接口隔离原则17

基本思想:将复杂的接口分离为多个单独的接口,以免强制实现者必须实现某些他们实际上并不需要的接口。

反例:多功能打印机可以完成打印接口,扫描接口

struct IMachine
{virtual void print(vector<Document*> docs) = 0;virtual void scan(vector<Document*> docs) = 0;
}

存在的问题:也许某个实现者仅仅需要打印功能但缺强制需要实现扫描的函数实现。

修复:将所有接口拆分开

struct IPrinter
{virtual void print(vector<Document*> docs) = 0;
}struct IScanner
{virtual void scan(vector<Document*> docs) = 0;
}// 打印机或扫描仪可以单独继承
// 如果想要一个同时有打印扫描功能
struct IMachine : IPrinter, IScanner
{
}

1.5.5 依赖倒转原则19

反例:Reporting 模块依赖ILogger接口

class Reporting
{ILogger& logger; // 依赖就是将对方作为自己的参数引入
}

存在的问题:当Reporting同时依赖5个不同的接口?

第一部分 创建型设计模式

回顾C++中创建对象的方法

  • 栈分配
  • 堆分配 new
  • unique指针
  • shared指针
  • weak指针
    函数返回比字节大的对象:
Foo func(){return Foo{n};
}

第2章 构造器模式26

构造器模式主要关注复杂对象的创建过程,复杂对象指的是难以通过调用单行构造函数来创建的对象。
2.1 预想方案26

2.2 简单构造器27

struct HtmlBuilder
{void add_child(){}
}
build.add_child( "hello" );

2.3 流式构造器28
2.4 向用户传达意图28
2.5 Groovy风格的构造器30
2.6 组合构造器32

2.7 参数化构造器35

强制用户使用构造器

MailService ms;
ms.send_email([&](auto& eb){
eb.from("foo@bar.com")
.to("bar@baz.com");
});

2.8 构造器模式的继承性36
2.9 总结39

第3章 工厂方法和抽象工厂模式41

3.1 预想方案41
3.2 工厂方法43
3.3 工厂44
3.4 工厂方法和多态46
3.5 嵌套工厂47
3.6 抽象工厂48
3.7 函数式工厂50
3.8 对象追踪51
3.9 总结52

第4章 原型模式53

4.1 对象构建53
4.2 普通拷贝54
4.3 通过拷贝构造函数进行拷贝54

4.4 “虚”构造函数56

virtual Address* clone()
{return new Address{street, city, suite};
}

4.5 序列化58
4.6 原型工厂60
4.7 总结61

第5章 单例模式62

5.1 作为全局对象的单例模式62

5.2 单例模式的经典实现63

防止被显示构建的唯一方式仍旧是将其构造函数声明为私有的。

struct Database
{
protected:Database();
public:static Database& get(){static Database database;return database;}
}

线程安全
单例模式初始化是线程安全的,不会遇到创建两次数据的情况。
5.3 单例模式存在的问题65
5.3.1 每线程单例68
5.3.2 环境上下文70
5.3.3 单例模式与控制反转73
5.3.4 单态模式73
5.4 总结74
第二部分 结构型设计模式
第6章 适配器模式77
6.1 预想方案77
6.2 适配器79
6.3 临时适配器对象80
6.4 双向转换器82
6.5 总结83
第7章 桥接模式85
7.1 Pimpl模式85
7.2 桥接模式介绍87
7.3 总结89

第8章 组合模式90

8.1 支持数组形式的属性91

8.2 组合图形对象93

只依赖于一个接口

struct GraphicObject
{virtual void draw()=0;
};// 继承
struct Circle : GraphicObject
{void draw() override{cout << "Circle" << endl;}
};struct Group : GraphicObject
{void draw() override{cout << "Group" << endl;}vector<GraphicObject*> Object;
};Group root( "root" );
Circle c1;
root.object.push_back( &c1 );

8.3 神经网络95
8.3.1 封装组合模式97
8.3.2 概念上的改进98
8.3.3 概念和全局运算符99
8.4 组合模式的规范100
8.5 总结101
第9章 装饰器模式103
9.1 预想方案103
9.2 动态装饰器104
9.3 静态装饰器107
9.4 函数装饰器108
9.5 总结111
第10章 外观模式112
10.1 幻方生成器112
10.2 构建贸易终端116
10.2.1 高级终端117
10.2.2 “外观”体现在哪里118
10.3 总结119

第11章 享元模式120

11.1 用户名问题120

大量重复的用户名,占用空间。可以只存储一次名字,然后将存储指向具有该名字的用户指针。将姓名分成姓氏,名字更有意义。
11.2 Boost.Flyweight122
11.3 字符串的范围122
11.3.1 幼稚解法123
11.3.2 享元实现124
11.4 总结126
第12章 代理模式127
12.1 智能指针127
12.2 属性代理128
12.3 虚拟代理129
12.4 通信代理131
12.5 值代理133
12.6 总结135
第三部分 行为型设计模式
第13章 职责链模式138
13.1 预想方案138
13.2 指针链139
13.3 代理链141
13.4 总结144
第14章 命令模式145
14.1 预想方案145
14.2 实现命令模式146
14.3 撤销操作147
14.4 复合命令149
14.5 命令查询分离152
14.6 总结154
第15章 解释器模式155
15.1 解析整数155
15.2 数值表达式求值156
15.2.1 词法分析157
15.2.2 语法分析159
15.2.3 使用词法分析器和
语法分析器161
15.3 使用Boost.Spirit解析161
15.3.1 抽象语法树162
15.3.2 语法分析器163
15.3.3 打印器164
15.4 总结164
第16章 迭代器模式166
16.1 标准库中的迭代器166
16.2 遍历二叉树168
16.3 使用协程的迭代171
16.4 总结172
第17章 中介者模式174
17.1 聊天室174
17.2 中介者与事件178
17.3 中介者服务总线180
17.4 总结181
第18章 备忘录模式182
18.1 银行账户182
18.2 撤销功能和恢复功能183
18.3 内存注意事项186
18.4 使用备忘录进行交互操作186
18.5 总结187
第19章 空对象模式188
19.1 预想方案188
19.2 shared_ptr不是空对象190
19.3 设计改进190
19.4 隐式空对象191
19.5 与其他模式的交互191
19.6 总结192
第20章 观察者模式193
20.1 属性观察器193
20.2 Observer194
20.3 Observable195
20.4 连接观察者和被观察者196
20.5 依赖问题197
20.6 取消订阅与线程安全197
20.7 可重入性198
20.8 Boost.Signals2中的观察者模式200
20.9 视图201
20.10 总结203
第21章 状态模式204
21.1 状态驱动的状态转换204
21.2 设计状态机207
21.3 基于开关的状态机209
21.4 Boost.MSM状态机211
21.5 总结214

第22章 策略模式215

22.1 动态策略216

// 定义策略抽象类
struct ListStrategy
{virtual void add_list_item()
}struct MarkdownListStrategy : ListStrategy
{void add_list_item() override
}struct TextProcessor
{void append_list(){list_strategy->add_list_item();	}
private:
unique_ptr list_stratgy;
}void set_output_format(format)
{switch(format)  切换策略case markdownlist_strategy = ;
}TextProcessor tp.set_output_format(markdown)// 使用时设置策略

22.2 静态策略219
22.3 总结219

第23章 模板方法模式221

策略模式和模板方法非常相似。

23.1 游戏模拟221

定义游戏模板

class Game
{void run() // 玩游戏模板{start();while(!have_winner())take_turn();cout << "Player" << get_winner() << "wins.";}protected:virtual void start() = 0;// 具体类去实现virtual void have_winner() = 0;virtual void take_turn() = 0;virtual void get_winner() = 0;
}

23.2 函数式模板方法223

23.3 总结224

练习:

void Uplink::sndTcp()
{pkt_len = char ipheader + udp header + icmp headeriphdr *ip = pkttcphdr *tcp = ip+1build_headersend_pkt
}

第24章 访问者模式226
24.1 侵入式访问者227
24.2 反射式打印组件228
24.3 什么是分发230
24.4 经典访问者231
24.5 非循环访问者234
24.6 std::variant和std::visit236
24.7 总结237

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

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

相关文章

【bug】重复请求的幂等问题

问题背景 某验收系统,客户发起验收流程时,由于前端没有做防重点击的限制,导致申请按钮连续点击了多次,重复发起了多条流程 历史逻辑 后端为了保证接口幂等,在发起验收流程的代码中加了几层逻辑如下:判断验收记录状态是否为待发起, 如果不是,则立刻返回失败 发起流程的入…

Deformable DETR

PDF:https://arxiv.org/pdf/2010.04159 Code:https://github.com/fundamentalvision/Deformable-DETR 一、大体内容 前面介绍DETR时,说明了其还存在对小物体检测效果不佳和训练慢的问题,Deformable DETR引入了DCN(Deformable Convolutional Networks)并将其和DETR相结合,借…

【蓝队】HW中盛行的Java内存马,如何全面检测?

一、背景 1.1 Java内存马是什么? 内存马是一种仅在内存中运行、没有文件落地的恶意程序,因此具有较强的隐蔽性,能够避开常规的基于文件系统的检测。Java内存马是针对Java语言的内存马,它利用Java语言的动态特性,如类加载机制、动态代理和反射技术等,在Java应用的内存中注…

Express的使用笔记9 使用bcrypt算法给用户密码加密

先了解一下bcrypt算法,一种基于Blowfish密码学算法的密码散列函数,用于在密码存储时抵抗暴力破解攻击,通过在散列过程中加salt来提高安全性,salt是个随机生成的数据串,与密码一起被散列,使得即使两个相同的密码也会产生不同的散列值。bcrypt算法允许开发者指定工作因子(…

4.mysql中的存储过程

创建存储过程和函数 CREATE[DEFINER = {USER | CURRENT_USER}] # 定义者是谁PROCEDURE sp_name ([proc_parameter[,...]])[characteristic ...] routine_bodyCREATE [DEFINER = {USER | CURRENT_USER}]FUNCTION sp_name ([function_name[,...]])[characteristic ...] routine_…

印象笔记使用

vscode安装插件登录印象笔记,开通token点击插件页面的设置填写url和tokenctrl + shift + pever new - 新建笔记 ever open - 打开笔记 ever search - 搜索笔记 ever publish - 发布笔记 ever sync - 同步笔记新建笔记下载安装windows客户端,功能比网页端更全面客户端才能导出…

(BIBM-2024) 用于药物相互作用预测的可解释多视图注意网络

用于药物相互作用预测的可解释多视图注意网络 论文标题: Interpretable multi-view attention network for drug-drug interaction prediction 论文地址: https://ieeexplore.ieee.org/document/10385757 论文期刊: BIBM 2024 摘要 药物间相互作用(DDI)在药物发现中发挥着越来…

Volatility取证工具安装教程

linux安装vol2.6 1.准备工作 准备一台虚拟机,拥有python2版本(虚拟机以kali为例) 准备Volatility2.6安装包 volatilityfoundation/volatility: An advanced memory forensics framework 准备反编译库安装包 vext01/distorm3: distorm3 2.安装步骤详解(全程在root用户下操作…

[React]AntDesign 4.x 汉化

antd汉化,适用于4.x转载自:https://blog.csdn.net/weixin_43013802/article/details/132870349全局汉化,在main.ts中引入下面代码:import{ ConfigProvider }fromantd import locale from antd/locale/zh_CN; import dayjs/locale/zh-cn;ReactDOM.createRoot(document.getEl…

线性回归(linear regression)

其实线性回归不过就是在做两件事,画一条线并判断这条线到各个点的距离。 如下图:其中这条线便是距离各个点距离总和最小的直线。也就是e+u+w+b+a总和在直线为这个情况下最小。但是什么时候这条线是我们需要的线呢?-- 线到各个点最短的时候便是。 我们先理解一下什么是凹函数…

数据库安全性与权限管理

title: 数据库安全性与权限管理 date: 2024/12/16 updated: 2024/12/16 author: cmdragon excerpt: 数据库安全性与权限管理是保护数据不被未授权访问和操控的关键所在。通过实施有效的安全措施和细粒度的权限控制,可以确保数据库的完整性、机密性和可用性。 categories:前端…

数据整合+团队协作,电商选品效率提升100%!

选品快准狠!在线协同助力电商团队做出更聪明的决策 在电商行业,“选品”决定成败。无论是发现爆款、避开雷区,还是追踪最新趋势,每一个决策都离不开团队协作与信息整合。然而,大量的电商团队仍旧面临以下常见问题: - 决策过程拉长,错失销售机会。 - 数据不统一,选品思路…