awk

说明

  • 默认按空白符分隔(\s+),多个连续空白符不切分

  • 列数从 1 开始

打印

1
2
# 打印
ls -l | awk '{print $5}' # 打印第 5 列

统计

1
2
# 统计大小
ls -l | awk '{sum+=$5}END{print sum/1024/1024"MB"}'

黑苹果安装

说明

不定期更新装黑苹果的流程和问题处理,提供两个具体的基于 OpenCoreconfig.plist

流程

该流程基于 OpenCore,使用 Mac OS,config.plist 主要参考 这里,具体流程如下。

下载镜像

  • 百度搜索 黑果小兵,找下最新的系统镜像

制作启动盘

  • 如果无需制作多启动优盘,使用 etcher 写入即可
  • 如果需要制作多启动优盘,需要使用命令,参考 这里 制作

配置 OpenCore

异常

whatevergreen: failed to route IsTypeCOnlySystem

whatevergreenfailed to route IsTypeCOnlySystem 异常,如果是使用集显,需要调整 device-properties。

DSDT_HPET.aml

Dell Optiplex 7050 使用 OpenCore 0.6.5 安装 Big Sur (11.1) 后,板载声卡无法识别,Lilu.kext + AppleALC.kext 换各种 layout-id 无解。后参考这篇帖子,需要 fix Comment-IRQ,如果使用 Clover 的话,在 ACPI 勾选 FixHPETFixIPICFixRTCFixTMR 即可,使用 OpenCore 的话,略微麻烦。

首先,获取机器的 DSDT.aml ,参考这篇文章 ,我使用 UEFI Shell 方式,需要下载 acpidump.efi ,和 OpenShell.efi(在下载的 OpenCore 中) 一并放入 /EFI/OC/Tools 下面,并在 config.plist 的 Misc -> Tools 下面启用,具体参考文章。重启,在引导界面进入 Open Shell,输入如下命令。

1
2
3
4
5
6
shell> fs0: // 替换为实际分区,进入OpenShell后会有分区提示
fs0:\> dir // 查看分区文件,确认选的分区是否正确
Directory of fs0:\
01/01/01 3:30p EFI
fs0:\> cd EFI\OC\Tools
fs0:\EFI\OC\Tools> acpidump.efi -b -n DSDT -z

运行完上面命令后,会在EFI分区生成多个 *.dat 文件,我们把 dsdt.dat 拿出来,重命名为 DSDT.aml

然后,使用工具生成 SSDT-HPET.aml 文件。下载工具 SSDTTime,双击 SSDTTime.command 运行,选择 FixHPET - Patch Out IRQ Conflicts ,把生成好的 DSDT.aml 拖入终端,按照提示操作,最后会生成四个文件。

1
2
3
4
patches_Clover.plist
patches_OC.plist
SSDT-HPET.aml
SSDT-HPET.dsl

接下来,需要做的是拷贝文件和Patch,把 SSDT-HPET.aml 拷贝至 EFI/OC/ACPI 文件夹下,并用 OpenCore Configurator 打开 patches_OC.plist,把 ACPI 项内的数据复制至我们自己的 config.plist 中。

至此,大功告成。可解决 ALC255/ALC3243 声卡无法识别问题。

设计模式(一)之策略模式

目录

  • 引言
  • 观察者模式

引言

设计模式系列,主要参考 《Head First 设计模式》 一书。

模拟鸭子

有这样一个需求,需要设计模拟鸭子游戏,游戏中有多种鸭子,鸭子都会叫和游泳,但是有不同的外观。简单的,我们采用 继承 来实现。首先,定义抽象类 Duck。

1
2
3
4
5
6
7
8
9
10
11
public abstract class Duck {
public void quack() {
System.out.println("quack quack!");
}

public void swim() {
System.out.println("I am swimming!");
}

abstract void display();
}

基于基类Duck,我们创造绿头鸭和红头鸭。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 绿头鸭
public class MallardDuck extends Duck {
@Override
void display() {
System.out.println("green head");
}
}

// 红头鸭
public class RedHeadDuck extends Duck {
@Override
void display() {
System.out.println("red head");
}
}

会飞的鸭子

基于上面的鸭子,我们还需要添加会飞的技能。借助继承,我们在基类中添加飞行方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public abstract class Duck {
public void quack() {
System.out.println("quack quack!");
}

public void swim() {
System.out.println("I am swimming!");
}

public void fly() {
System.out.println("I am flying!");
}

abstract void display();
}

但是,可怕的事情发生了。在添加橡皮鸭的时候,竟然会飞!因为疏于设计,导致局部的修改,影响到了所有的鸭子对象。该怎么办呢?试下 覆盖 吧,在橡皮鸭中,实现飞行方法,覆盖父类行为,但是什么都不做。

1
2
3
4
5
6
7
8
9
10
11
12
public class RubberDuck extends Duck {

@Override
public void fly() {
// do nothing
}

@Override
void display() {
System.out.println("I am rubber duck");
}
}

似乎,解决了问题。是不是可以使用接口呢,只有会飞的鸭子才实现此接口。

但是如此,重复代码会增加,因为对同样的行为需要重复实现,比如需要对所有呱呱叫的鸭子,需要在 quack 方法中实现呱呱叫的行为。

问题归零,来重新设计。继承不能很好地解决问题,因为鸭子的行为在不断的改变,并且让鸭子实现具有所有行为是不合理的。接口 不具有具体实现,所以继承接口无法实现代码复用。

找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。 把会变化的部分取出并封装,好让其他部分不受影响。依据此原则,把鸭子的行为从 Duck 类中抽取出来。把 Duck 类中的 flyquack 会随鸭子不同而变化的行为,从 Duck 类中分开。

我们希望设计具有弹性,可以指定行为到鸭子实例。可以把鸭子的行为放在分开的类中,专门提供某行为接口的实现。**针对接口编程,而不是针对实现编程。**利用接口代表每个行为,比如 FlyBehaviorQuackBehavior ,行为的每个实现都将实现其中的一个接口。这次,鸭子类不负责实现 Flying 和 Quacking 接口,由我们制造一组其他类专门实现 FlyBehaviorQuackBehavior,这称为行为类。

针对接口编程真正的意思是针对超类型 (supertype)编程。利用多态,程序可以针对超类型编程,执行时会根据 实际状况执行到真正的行为。

1
2
3
4
5
6
7
8
9
10
11
// 针对实现编程
Dog d = new Dog( );
d.bark( );

// 针对接口/超类型编程
Animal animal = new Dog( );
animal.makeSound( );

// 行时指定具体实现
Animal a = getAnimal( );
a.makeSound( );

最终的实现如下。

至此。

少用继承,多用组合。

策略模式 定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

要点 良好的OO设计必须具备 可复用、可扩充、可维护 三个特性,模式可以让我们构建出具有良好OO设计质量的系统。

定义

生成

遍历

前序遍历

中序遍历

后续遍历

深度优先遍历(DFS)

广度优先遍历(BFS)

应用

红黑树

R-B Tree,全称是Red-Black Tree,又称为“红黑树”,它一种特殊的二叉查找树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black),红黑树有如下特性。

  • 每个节点或者是黑色,或者是红色。
  • 根节点是黑色。
  • 每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
  • 如果一个节点是红色的,则它的子节点必须是黑色的。
  • 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

红黑树是一种特化的AVL树(平衡二叉树),都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中非常高效。

应用

  • Java 中的 TreeSet、TreeMap
  • C++ STL 中的 set、map
  • Linux 虚拟内存的管理

搜索二叉树(BST)

二叉查找树实际上是数据域有序的二叉树,即对树上的每个结点,都满足其左子树上所有结点的数据域均小于或等于根结点的数据域,右子树上所有结点的数据域均大于根结点的数据域。

平衡二叉树(AVL)

平衡二叉树是由前苏联的两位数学家G.M.Adelse-Velskil和E.M.Landis提出,因此一般也称作AVL树,AVL树本质还是一棵二叉查找树,只是在其基础上增加了“平衡”的要求。所谓平衡是指,对AVL树的任意结点来说,其左子树与右子树的高度之差的绝对值不超过1,其中左子树与右子树的高度因子之差称为平衡因子。

B/B+/B* 树

B树

B 树是一种多路搜索树(非二叉树),其具有如下特点。

  • 定义任意非叶子结点最多只有M个儿子;且M>2;

  • 根结点的儿子数为[2, M];

  • 除根结点以外的非叶子结点的儿子数为[M/2, M];

  • 每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)

  • 非叶子结点的关键字个数=指向儿子的指针个数-1;

  • 非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];

  • 非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的

    子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;

  • 所有叶子结点位于同一层;

问题

B树和B+树的区别

  • B 树每个节点都保存key和data,B+ 树的data存储在叶子节点上
    • 非叶子节点不存储数据,这样一个节点可存储更多key,使树更矮,减少查找 / IO次数
  • 树的所有叶节点构成一个有序链表,可以按照key的排序次序遍历全部数据
    • 由于数据顺序排列且相连,便于区间查找和搜索

索引为什么使用B+树,而不是哈希表或B树

对应磁盘中的数据读取,应尽量优化磁盘访问次序。磁盘读取是按块读取的,充分利用这个原理,可减少磁盘访问次数。

索引使用B+树,相对于B树来说,非叶子结点保存数据更多,一次读取磁盘,可便利的key范围更广,所以理论上度写磁盘次数更少。

B+树,相对于哈希表来说,哈希索引也不支持多列联合索引的最左匹配规则,且无法按key的范围查找。

类图

关系

继承(Inheritance / Extension)

关系 连线
继承,子类特化父类所有特征和行为 带箭头实线,箭头指向父类

示例

接口(Interfaces)

关系 连线
类实现接口 带三角箭头的虚线,箭头指向接口

虚线

关联(Associations)

可双向关联,也可单向关联,或自身关联。

关系 连线 代码
拥有关系,使一个类可以知道其他类的属性和方法 实心线,单向关联使用普通箭头,指向被拥有者;双向关联无箭头 成员属性

示例

聚合(Aggregation)

关系 连线 代码
部分和整体的关系,部分可离开整体独立存在 空心菱形实心线,菱形指向整体 成员属性

示例

组合(Composition)

关系 连线 代码
部分和整体的关系,部分不可离开整体独立存在 实心菱形实心线,菱形指向整体 成员属性

依赖(Dependency)

关系 连线 代码
使用关系 带箭头的虚线,指向被使用者 局部变量、方法的参数或者对静态方法的调用

示例

示例

Example UML Class Diagram

参考

领域驱动设计(Domain-Driven Design)

领域驱动设计(DDD,Domain-Driven Design)是帮助开发大型系统的原则和模式的集合。DDD 更像一种方法论,指导我们开发大型的系统。

软件系统设计理念经历了 POP(面向过程编程)、OOP(面向对象编程)、DDD(领域驱动设计) 的转变。POP 设计,通过构建函数、分层,划分模块等方式,分解软件系统的复杂度。OOP 把软件的设计从功能维度提升到实体维度,进一步分解软件系统的复杂度,并以一种更易于理解的方式来组织软件系统。

随着软件系统规模的不断扩大,面临着实体爆炸的问题,在一个单一的逻辑范畴内,处理所有的实体,到了极其复杂的程度。DDD 通过把系统从需求维度划分为不同的领域,每个领域进行单独的设计,域之间通过暴露接口来进行协作。

核心概念

contexts

构成要素

  • 实体(Entity)
  • 值对象(Value Objects)
  • 领域服务(Domain Service)
  • 聚合根(Aggregate Root)
  • 工厂(Factories)
  • 仓储(Repository)

Bounded Context

contexts

参考

plantuml 类图

声明元素

1
2
3
4
5
6
7
8
9
10
11
12
13
@startuml
abstract abstract
abstract class "abstract class"
annotation annotation
circle circle
() circle_short_form
class class
diamond diamond
<> diamond_short_form
entity entity
enum enum
interface interface
@enduml

定义关系

关系 符号
扩展(Extension) <|–
组合(Conposition) *–
聚合(Aggregation) o–

示例

1
2
3
4
5
6
7
8
9
10
11
@startuml
class Dummy {
String data
void methods()
}

class Flight {
flightNumber : Integer
departureTime : Date
}
@enduml