Cpp 设计模式笔记——3. 结构型模式
Adapter (适配器) 适配器模式是一种结构型设计模式,它使接口不兼容的对象能够相互合作。 假设我们已有一个现有类Adaptee,它提供接口specificRequest(),客户端希望调用接口类Target的request()方法, 两个接口无法直接相连,并且可能存在一些差异,例如函数参数顺序。 出于某些原因,我们无法更改旧有代码,那么可以选择在其中加上适配器Adapter: 适配器Adapter直接继承接口类Target,可以对客户端提供request()方法; 适配器Adapter将现有类Adaptee作为数据成员,在request()方法中实际调用Adaptee对象的specificRequest(),在传递过程中还需要处理一些差异,例如调整函数参数顺序。 示例代码如下 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748#include <iostream>#include <memory>#include <...
Cpp 设计模式笔记——2. 创建型模式
Factory Method (工厂方法) 工厂方法模式是一种创建型设计模式,其在父类中提供一个创建对象的方法,允许子类决定实例化对象的类型。 我们需要定义两个抽象类:产品基类Product和工厂基类Factory,后者提供创建产品的方法createProduct()。 具体产品(ProductA、ProductB)需要继承自产品基类Product。 每一个产品都需要提供配套的工厂(FactoryA、FactoryB),工厂需要继承自工厂基类Factory,对创建产品的方法提供不同的实现。 示例代码如下 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556#include <iostream>#include <memory>// 产品接口struct Product { virtual void describe() const = 0; virtual ~Product() ...
Cpp 设计模式笔记——1. 概述
有必要学一下设计模式,虽然在大部分情况下都是基于Java语言来讨论设计模式,但是面向对象的思想对于各种语言都是通用的,这一系列笔记将使用C++进行讨论。 设计原则 通常设计模式遵循七个基本原则,如下文所示。有的教程中只有六个基本原则,不含单一职责原则。 单一职责原则 每个类应该只有一个职责,即该类只有一个引起变化的原因。 这样可以减少类之间的耦合,提高系统的可维护性。 与单一职责原则相违背的极端做法是使用上帝对象,它负责了太多的职责,了解了太多的信息,这会导致代码的修改和维护非常困难。 考虑一个情景,我们需要实现一个简单的文件管理类:读取文件内容并输出到控制台,向文件中写入指定内容,我们希望在读写操作的同时在控制台中输出日志。 不符合单一职责原则的例子如下 123456789101112131415161718192021222324252627282930313233343536373839#include <fstream>#include <iostream>#include <string>class FileManager &...
Fish Shell 配置笔记
记录一下关于fish的使用和配置。 概述 fish和zsh是最常见的两种用于替代默认bash的现代shell,两者的定位有点区别: fish对用户友好,开箱即用,不需要复杂配置,缺点是语法与bash不兼容; zsh兼容bash的语法,缺点是必须进行较复杂的配置,否则和bash使用体验差不多。 对这些shell的主题配置,通常都会基于oh-my-zsh、oh-my-fish以及pwsh的oh-my-pwsh这些美化工具进行, 但是鉴于fish的开箱即用特点,我决定不使用美化工具,默认的就可以了。 由于fish不兼容bash的语法,因此通常不建议将其作为默认shell使用,而是在登陆后手动开启fish 1fish 这样我们可以继续使用bash的.bashrc进行环境变量等配置,fish也会自动继承相应的配置。 日常操作中最好也是继续使用bash脚本,通过shebang的方式指定使用bash。 使用 fish默认支持实时更新的彩色显示,对于无效命令使用红色进行警告,有效命令则显示为蓝色,对于有效路径会显示下划线提示。 (这些默认行为都可以通过配置修改) fish会自动给出命令提示,...
什么是高质量的代码
学习并整理一下个人的理解:什么样的代码是高质量的代码? 代码的评价指标 这部分内容主要参考知乎上的回答:什么样的代码是高质量的代码? - 王争的回答 - 知乎。 简洁性 KISS原则:“Keep It Simple,Stupid” 我们需要通过尽可能简单的代码来完成目标,避免炫技地引入复杂的结构和设计模式。 典型的反例就是Java,完全的面向对象导致了代码架构的过度复杂化。例如程序员需要点一杯咖啡,Java 风格的代码如下 12345CoffeeFactoryBuilderSingletonManagerProvider.getCoffeeFactoryBuilderSingleton() .getCoffeeBuilder() .addMilk() .addSugar() ...
Euler 方程组的 Riemann 问题精确解
Euler方程组是典型的双曲守恒律方程组,Riemann问题是为探究双曲守恒律模型的间断问题所设置的模型,我们考虑一维Euler方程组的Riemann问题精确解求解。 \[ \begin{aligned} \begin{pmatrix} \rho \\ \rho u \\ E \end{pmatrix}_t + \begin{pmatrix} \rho u \\ \rho u^2 + p \\ u(E + p) \end{pmatrix}_x = 0,\,\,\, E = \frac12 \rho u^2 + \frac{p}{\gamma-1} \end{aligned} \] Riemann问题介绍 对于无界计算区域 \(x \in \mathbb{R}\),Riemann问题指的是初值在\(x=0\)两侧取不同的常数值,在\(x=0\)存在一个间断,即 \[ \mathbf{U}(x,0) = \left\{ \begin{aligned} &\mathbf{U}_l, x < 0\\ &\mathbf{U}_r, x > 0\\ \end{al...
MATLAB 绘图速查笔记
MATLAB的语法学习曲线很特别:入门时用起来特别简单舒服,但是深入学下去就会感觉到语法非常混乱,无所适从。 尤其在绘图部分,MATLAB杂揉了命令式语句和面向对象的语句,存在太多的语法糖,毫无逻辑性可言。 记录一些关于绘图的代码吧,便于查找。 绘制多条曲线 绘制多条曲线 1234567891011121314151617181920212223x = linspace(0, 2*pi, 100);y1 = sin(x);y2 = cos(x);y3 = sin(2*x);figure;hold on;plot(x, y1, 'r-', LineWidth=2, DisplayName='sin(x)');plot(x, y2, 'b--', LineWidth=2, DisplayName='cos(x)');plot(x, y3, 'g:', LineWidth=2, DisplayName='sin(2x)');hold off;title('M...
MATLAB 并行计算
整理一下关于MATLAB并行计算的内容,主要是Parallel Computing Toolbox工具包的内容,本文内容暂不涉及集群层面的并行,也不涉及GPU的使用。 本文部分参考了下列官方文档: parfor、spmd和parfeval的对比。 后台处理。 parfor 将for循环改成parfor循环是最简单直接的并行方式,它会启动不同的进程/线程来同步执行循环,这对循环中的内容有一定的要求: 每次迭代相互独立,结果不依赖于其他迭代 不支持某些动态操作变量的函数,如 eval 和 assignin 循环次数必须明确,不能依赖于运行时的计算结果 不支持嵌套的parfor循环 对于简单的循环体,可以尝试直接用矢量化的语法,因为parfor在启动和结束过程中也会带来额外的时间成本。 在parfor循环体内部,变量被大致分为如下几类: 循环变量,对它的限制是在循环内不能对循环变量再次赋值,并且不要在循环体外部再次使用,因为并行会导致无法确定循环变量的具体值 1234parfor i = 1:n i = i + 1; % not allowed a(i) = i...
Git 使用规范
分支规范 分支的命名习惯上使用小写字母、数字、连字符-以及斜杠/组成。 这里建议使用斜杠/因为它会被Git自动识别,并且在.git/中为其创建目录结构,例如.git/refs/heads/feature/xxx。 复杂项目 对于使用多个平行分支进行版本管理的复杂项目,分支的命名和使用通常遵循如下规范: 两个长期分支: 主分支:包括项目的所有正式版本,名称为main或master; 开发分支:包括项目的最新版本,名称为develop、dev或next; 几种短期分支:(向长期分支合并完成后即可删除) 功能分支:拆分为多个独立功能进行同步开发,名称例如feature/login-page,feature/user_module; 预发布分支:在正式版本发布之前的准备,名称例如release/xxx,xxx代表日期;(改为pre-release可能更合适) 快速修复分支:名称例如hotfix/xxx,xxx代表修复的问题编号或描述。 关于长期分支的使用: 主分支和开发分支作为一组平行线长期存在; 主分支上的结点主要是发布的稳定版本,在结点上加上对应的版本标签(例如v1.0...
Python 命令行参数解析 argparse
Python经常被用来写一下简化操作的脚本,并且要求脚本支持一定的选项,有必要整理一下Python命令行参数解析的用法。 Python自带的argparse模块功能已经非常强大,使用非常便捷。 Python其实还有另外两个模块可以完成同样的任务:getopt和optparse,但是前者过于简单,后者已经被弃用,目前只推荐使用argparse。 与之形成鲜明对比的是,C/C++对这种基础的需求通常都是直接手写的,或者去下载一些第三方提供的纯头文件库,为这种简单的任务引入外部依赖其实也并不合算,不如直接自己写了。 极简例子 从最简单的例子开始 test.py123import argparseparser = argparse.ArgumentParser()parser.parse_args() 这两行的含义为:设置一个参数解析器,解析参数。 直接运行脚本,无事发生 1python test.py 空的参数解析器为我们提供了--help(-h)参数,可以打印使用帮助,例如 1python test.py -h 输出形如 1234usage: test.py [-h]option...