完善:完善《软件设计师知识点速记》

This commit is contained in:
2023-05-11 23:40:37 +08:00
parent 0ce690ddbe
commit 0b5300d1dd

View File

@@ -1,5 +1,5 @@
---
title: 软件设计师知识点速记
title: 软件设计师知识点速记:计算机组成与体系结构
author: 查尔斯
date: 2023/05/06 21:10
categories:
@@ -9,13 +9,11 @@ tags:
- 软件设计师
---
# 软件设计师知识点速记
# 软件设计师知识点速记:计算机组成与体系结构
## 计算机组成与体系结构
## 进制转换
### 进制转换
#### R 进制 => 十进制
### R 进制 => 十进制
R 进制转十进制使用 **按权展开法** ,其具体操作方式为:将 R 进制数的每一位数值用 $R^k$ 形式表示,即幂的底数是 R指数为 kk 与该位和小数点之间的距离有关。当该位位于小数点左边k 值是该位和小数点之间数码的个数而当该位位于小数点右边k 值是负值,其绝对值是该位和小数点之间数码的个数加 1。
@@ -50,7 +48,7 @@ $$
$$
:::
#### R 进制 <= 十进制
### R 进制 <= 十进制
十进制转 R 进制使用 **短除法** ,简单来说就是将十进制数除 R 取余余数为权位上的数得到的商值继续除R依此步骤继续向下运算直到商为 0 为止。然后从最后一个余数读到第一个即为我们转换的 R 进制。
@@ -60,7 +58,7 @@ $$
![202305062208011](../../../../../public/img/2023/05/06/202305062208011.png)
#### 二进制 => 八进制
### 二进制 => 八进制
每 3 位二进制数 **按权展开** 相加得到 1 位八进制数,二进制转成八进制是从右到左开始转换,不足位时补 0。
@@ -80,7 +78,7 @@ $$
$$
:::
#### 二进制 <= 八进制
### 二进制 <= 八进制
上方提到了,二进制数转换为八进制,是用 3 位二进制数表示 1 位八进制数。反之八进制数转换为二进制数,那就需要用 1 位八进制数来表示 3 位二进制数。
@@ -94,7 +92,7 @@ $$
**结果为226O = 10010110B**
#### 二进制 => 十六进制
### 二进制 => 十六进制
与二进制转八进制方法类似,转八进制是取三合一,转十六进制是取四合一。即每 4 位二进制数 **按权展开** 相加得到 1 位十六进制数。
@@ -106,7 +104,7 @@ $$
**结果为100101110B = 12CH**
#### 二进制 <= 十六进制
### 二进制 <= 十六进制
二进制数转换为十六进制数,是用 4 位二进制数表示 1 位十六进制数。反之十六进制数转换为二进制数,那就需要用 1 位十六进制数来表示 4 位二进制数。
@@ -124,11 +122,11 @@ $$
十六进制中,每位的最大值为 15但如果用十进制的写法的话就占用了 2 位,所以十六进制中,使用 A 表示 10、B 表示 11、C 表示 12、D 表示 13、E 表示 14、F 表示 15。
:::
### 码制的表示
## 码制的表示
在计算机中,数字通常以二进制形式表示,也就是由 0 和 1 组成的数字序列。为了方便计算机进行数学运算,计算机需要使用一些编码方式来表示数字,其中最常用的编码方式是原码、反码、补码和移码。
#### 码制运算
### 码制运算
| | 数值1 | 数值-1 |
| ---- | --------- | --------- |
@@ -143,16 +141,16 @@ $$
> **取反:** 原来为 0 则变为 1原来为 1 则变为 0。真假变换
- 补码:补码是为了解决反码的问题而出现的。补码的规则是:正数的补码与原码相同,负数的补码是它的反码加 1。例如+5 的补码还是 **0**0000101-5 的补码是 **1**1111011。
- **补码** :补码是为了解决反码的问题而出现的。补码的规则是:正数的补码与原码相同,负数的补码是它的反码加 1。例如+5 的补码还是 **0**0000101-5 的补码是 **1**1111011。
> 补码具有会溢出的特性,适合参与进行加减法运算。
- 移码:移码是将补码的符号位取反,其余位不变。例如,+5 的移码是 **1**0000101-5 的移码是 **0**1111010
- 移码:移码是将补码的符号位取反,其余位不变。例如,+5 的移码是 **1**0000101-5 的移码是 **0**1111011
这些编码方式在计算机中都有广泛的应用,不同的编码方式有不同的优缺点,具体使用哪种编码方式取决于具体的应用场景。
::: tip 笔者说
::: warning 笔者说
在上方补码介绍中,提到了二进制数计算加 1 的问题,**1**1111010 + 1 = **1**1111011这个很简单但如果是 **1**1111011 + 1 呢?其实也很简单,注意的就是二进制每位最大值是 1如果每位 > 1 也就是 2 的时候就要进 1 了(逢 2 进 1
@@ -162,10 +160,99 @@ $$
--------
11111100 (结果)
```
:::
#### 数值范围
::: details 为什么有原、反、补码之分?
> 在学习原码,反码和补码之前,需要先了解机器数和真值的概念。
>
> 1. 机器数一个数在计算机中的二进制表示形式叫做这个数的机器数。机器数是带符号的在计算机用一个数的最高位存放符号正数为0负数为 1。
>
> 例如:十进制中的数 +3计算机字长为 8 位,转换成二进制就是**0**0000011。如果是 -3 ,就是 **1**0000011。
>
> 那么,这里的 **0**0000011 和 **1**0000011 就是机器数。
>
> 2. 真值:因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如:上面的有符号数 **1**0000011其最高位 1 代表负,其真正数值是 -3 而不是形式值 13110000011 转换成十进制等于131。所以为区别起见将带符号位的机器数对应的真正数值称为机器数的真值。
>
> 例如:**0**000 0001 的真值 = +000 0001 = +1**1**000 0001 的真值 = 000 0001 = 1
首先,因为人脑可以知道第一位是符号位,在计算的时候我们会根据符号位选择对真值区域的加减。但是对于计算机,加减乘数已经是最基础的运算,要设计的尽量简单。计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂!于是人们想出了将符号位也参与运算的方法。我们知道,根据运算法则减去一个正数等于加上一个负数,即:`1 - 1 = 1 + (-1) = 0` ,所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了。
于是人们开始探索将符号位参与运算,并且只保留加法的方法。首先来看原码:
例如计算十进制的表达式1 - 1 = 0。
$$
1 - 1 = 1 + (-1) = [00000001]_原 + [10000001]_原 = [10000010]_原 = -2D
$$
```
00000001 (原码)
10000001 (原码)
--------
10000010 (原码)
```
如果用原码表示,让符号位也参与计算,显然对于减法来说,结果是不正确的。这也就是为何计算机内部不使用原码表示一个数。
为了解决原码做减法的问题,出现了反码:
$$
1 - 1 = [00000001]_反 + [11111110]_反 = [11111111]_反 = [10000000]_原 = -0D
$$
```
00000001 (反码)
11111110 (反码)
--------
11111111 (反码)
```
发现用反码计算减法,结果的真值部分是正确的。而唯一的问题其实就出现在"0"这个特殊的数值上。虽然人们理解上 `+0``-0` 是一样的,但是 0 带符号是没有任何意义的。而且会有 `[0000 0000]原``[1000 0000]原` 两个编码表示0。除此之外虽然相反数相加没有问题但是其他数的减法依旧不对劲。
例如计算十进制的表达式2 - 1 = 1。
$$
2 - 1 = 2 + (-1) = [00000010]_反 + [11111110]_反 = [00000000]_反 = [00000000]_原 = 0D
$$
```
00000010 (反码)
11111110 (反码)
--------
100000000 (反码) -> 最高位 1 溢出,则结果为 00000000
```
所以,这个码还是不行。
于是补码出现了,不仅解决了 0 的符号问题:
$$
1-1 = 1 + (-1) = [00000001]_原 + [10000001]_原 = [00000001]_补 + [11111111]_补 = [00000000]_补 = [00000000]_原 = 0D
$$
```
00000001 (补码)
11111111 (补码)
--------
00000000 (补码)
```
这样 0 用 `[00000000]` 表示,而以前出现问题的 `-0` 则不存在了。[^1]
还解决了负数加法的问题:
$$
2 - 1 = 2 + (-1) = [00000010]_补 + [11111111]_补 = [00000001]_补 = [00000001]_原 = 1D
$$
```
00000010 (补码)
11111111 (补码)
--------
100000001 (反码) -> 最高位 1 溢出,则结果为 00000001
```
所以,在计算机系统中,数据分为原码反码和补码三种,并且,不论整数或负数,一律用补码来表示和存储。而且,由于反码、补码都是为了解决负数的问题而产生的变化,正数则没有变化,这也是为什么正数的反码、补码和原码一致的原因了。
:::
### 数值范围
| 码制 | 定点整数 | 定点小数 |
| ---- | ------------------------------------ | ------------------------------------------- |
@@ -174,7 +261,7 @@ $$
| 补码 | $-2^{n-1} \sim + (2^{n-1} - 1)$ | $-1 \sim + (1 - 2^{-(n-1)})$ |
| 移码 | $-2^{n-1} \sim + (2^{n-1} - 1)$ | $-1 \sim + (1 - 2^{-(n-1)})$ |
在一个字长为 n8 位原码)的计算机中,原码可以表示的数值范围为:**1**1111111 ~ **0**1111111将除符号位之外的数值位转换为十进制
在一个字长为 n (例如:字长为 8)的计算机中,原码可以表示的整数数值范围为:**1**1111111 ~ **0**1111111将除符号位之外的数值位转换为十进制
$$
1111111B = 1 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 1 * 2^2 + 1 * 2^1 + 1 * 2^0 = 127D
$$
@@ -182,16 +269,94 @@ $$
$$
-(2^{n-1} -1) \sim + (2^{n-1} - 1)
$$
原码和反码之所以负数要 - 1 主要是存在 -0 的表示,而补码、移码则不存在 -0所以也不需要 - 1了。
::: tip
其中 -128 的补码为 1000 0000-1 的补码是 1000 0000 是人为规定的。
:::
## 浮点运算
浮点数表示:
$$
N = 尾数 * 基数^{指数}
$$
运算过程:
$$
对阶 > 尾数计算 > 结果格式化
$$
特点:
1. 一般尾数用补码,阶码用移码
2. 阶码的位数决定数的表示范围,位数越多范围越大
3. 尾数的位数决定数的有效精度,位数越多精度越高
4. 对阶时,小数向大数看齐
5. 对接是通过较小数的尾数右移实现的
## 计算机结构
运算器:
1. 算术逻辑单元 ALU数据的算术运算和逻辑运算
2. 累加寄存器 AC通用寄存器为 ALU 提供一个工作区,用在暂存数据
3. 数据缓冲寄存器 DR写内存时暂存指令或数据
4. 状态条件寄存器 PSW存状态标志与控制标志
(争议:也有将其归为控制器的)
控制器:
1. 程序计数器 PC存储下一条要执行指令的地址
2. 指令寄存器 IR存储即将执行的指令
3. 指令译码器 ID对指令中的操作码字段进行分析解释
4. 时序部件:提供时序控制信号
## 计算机体系结构分类-Flynn
| 体系结构类型 | 结构 | 关键特性 | 代表 |
| -------------------------- | ---------------------------------------------------- | -------------------------------------- | ---------------------------------------------- |
| 单指令流单数据流<br />SISD | 控制部分:一个<br />处理器:一个<br />主存模块:一个 | | 单处理器系统 |
| 单指令流多数据流<br />SIMD | 控制部分:一个<br />处理器:多个<br />主存模块:多个 | 各处理器以异步的形式执行同一条指令 | 并行处理机<br />阵列处理机<br />超级向量处理机 |
| 多指令流单数据流<br />MISD | 控制部分:多个<br />处理器:一个<br />主存模块:多个 | 被证明不可能,至少是不实际 | 目前没有,有文献称流水线计算机为此类 |
| 多指令流多数据流<br />MIMD | 控制部分:多个<br />处理器:多个<br />主存模块:多个 | 能够实现作业、任务、指令等各级全面并行 | 多处理机系统<br />多计算机 |
## 指令的基本概念
一条指令就是机器语言的一个语句,它是一组有意义的二进制代码,指令的基本格式为:操作码字段|地址码字段。
操作码部分指出了计算机要执行什么性质的操作,如加法、减法、取数、存数等。地址码字段需要包含各操作数的地址及操作结果的存放地址等,从其地址结构的角度可以分为三地址指令、二地址指令、一地址指令和零地址指令。
## 寻址方式
- 立即寻址方式:操作数直接在指令中,速度快,灵活性差
- 直接寻址方式:指令中存放的是操作数的地址
- 间接寻址方式:指令中存放了一个地址,这个地址对应的内容是操作数的地址
- 寄存器寻址方式:寄存器存放操作数
- 寄存器间接寻址方式:寄存器内存放的是操作数的地址
## CISC 和 RISC
| 指令系统类型 | 指令 | 寻址方式 | 实现方式 | 其他 |
| ------------------ | ------------------------------------------------------------ | ---------- | ---------------------------------------------------- | ---------------------------------------------- |
| CISC复杂指令集 | 数量多,使用频率差别大,可变长格式 | 支持多种 | 微程序控制技术(微码) | 研制周期长,编译子程序库小 |
| RISC精简指令集 | 数量少,使用频率接近,定长格式,大部分为单周期指令,操作寄存器,只有 Load/Store 操作内存。 | 支持方式少 | 增加了通用寄存器,硬布线逻辑控制为主,适合采用流水线 | 优化编译,有效支持高级程序语言,编译子程序库大 |
## 流水线技术
流水线是指在程序执行时多条指令重叠进行操作的一种准并行处理实现技术。各种部件同时处理时针对不同指令而言的,它们可同时分为多条指令的不同部分进行工作,以提高各部件的利用率和指令的平均速度。
相关参数计算:
- 流水线建立时间:第 1 条指令执行时间
- 流水线周期:指令分段后,最长段时间
- 流水线执行时间(默认使用理论公式,无答案时考虑实践公式)
- 理论公式:流水线建立时间+(指令条数-1)x流水线周期
- 实践公式指令段数x流水线周期+(指令条数-1)x流水线周期
- 吞吐率=指令条数/流水线执行时间
- 最大吞吐率=流水线周期的倒数
- 流水线吞吐率=指令条数/流水线执行时间
- 流水线最大吞吐率=流水线周期的倒数
吞吐率和建立时间是使用流水线技术的两个重要指标。吞吐率是指单位时间里流水线处理机流出的结果数。
@@ -199,162 +364,89 @@ $$
::: details 2009上半年某指令流水线由 5 段组成,第 1、3、5 段所需时间为 $\Delta t$,第 2、4 段所需时间分别为 $3\Delta t$、$2\Delta t$,如下图所示,那么连续输入 n 条指令时的吞吐率单位时间内执行的指令个数TP 为______。
**答:** 连续输入 n 条指令时,第 1 条指令需要的时间为 $(1+3+1+2+1)\Delta t$,之后,每隔 $3\Delta t$ 便完成 1 条指令,即流水线一旦建立好,其吞吐率为最长子过程所需时间的倒数。综合 n 条指令的时间为 $(1+3+1+2+1)\Delta t+(n-1)\times 3\Delta t$,因此吞吐率为:
**答:** 连续输入 n 条指令时,第 1 条指令需要的时间为 $(1 + 3 + 1 + 2 + 1)\Delta t$,之后,每隔 $3\Delta t$ 便完成 1 条指令,即流水线一旦建立好,其吞吐率为最长子过程所需时间的倒数。综合 n 条指令的时间为 $(1 + 3 + 1 + 2 + 1)\Delta t + ( n - 1)\times 3\Delta t$,因此吞吐率为:
$$
\frac{n}{(3+3+2)\Delta t+3(n-1)\Delta t}
\frac{n}{(3 + 3 + 2)\Delta t + 3(n - 1)\Delta t}
$$
:::
## McCabe 复杂度计算
## 层次化存储结构
McCabe复杂度计算公式V(G)=m-n+2其中 m 是有向弧的条数n 是结点数。
- CPU寄存器最快但容量小成本高
- Cache按内容存取
- 内存(主存):
- 随机存储器RAM
- 只读存储器ROM
- 外存辅存硬盘、光盘、U盘等
对于伪代码可以先转换为程序流程图,对程序流程图可以最终转换为结点图处理,转换时注意将交点的地方标注为新的结点,以最终的结点图带入公式结算其 McCabe 复杂度
局部性原理是层次化存储结构的支撑
## DFD数据流图
## Cache
### 数据流常见的 3 种错误
### 概念
- 黑洞:加工只有输入没有输出
- 奇迹:加工只有输出而没有输入
- 灰洞:加工中输入不足以产生输出(输入的数据流无法通过加工产生输出流)
在计算机的存储系统体系中Cache 是访问速度最快的层次(若有寄存器,则寄存器最快)。
## UML
使用 Cache 改善系统性能的依据是程序的局部性原理。
### UML 图分类
如果以 h 代表对 Cache 的访问命中率,$t_1$ 表示 Cache 的周期时间,$t_2$ 表示主存储器周期时间,以读操作为例,使用 “Cache + 主存储器” 的系统的平均周期为 $t_3$,则:
$$
t_3 = h * t_1 + (1 - h) * t_2
$$
其中1 - h又称为失效率未命中率
UML 2.0 分为结构图和行为图。
### 映像
结构图:
- 直接相联映像:硬件电路较简单,但冲突率很高
- 类图
- 对象图
- 包图*
- 组合结构图*
- 构件图
- 部署图:软硬件之间映射
- 制品图*
- 全相联映像:电路难于设计和实现,只适用于小容量的 Cache冲突率较低
行为图:
- 组相联映像:直接相联与全相联的折中
- 用例图:系统与外部参与者的交互
- 顺序图:强调按时间顺序
- 通信图(协作图)
- 定时图*
- 状态图
- 活动图:类似程序流程图,并行行为
- 交互概览图*
- 地址映像是将主存与 Cache 的存储空间划分为若干大小相同的页(或称为块)。
### 类图关系
例如:某机的主存容量为 1GB划分为 2048 页,每页 512KBCache 容量为 8MB划分为 16 页,每页 512KB。
- 组合关系:整体与部分生命周期相同
- 例如:大雁和翅膀属于组合关系
- 聚合关系:整体与部分生命周期不同
- 例如:大雁和雁群属于聚合关系
- 依赖关系:一个事物发生变化影响另一个事物
- 例如y=x+1我们就说 y 依赖于 xy 的值随着 x 的值变化而变化
- 泛化关系:父子关系,一般与特殊的关系
- 例如:动物类和猫类
- 实现关系:接口与类之间的关系
- 关联关系:两者之间用链进行连接,一般表示两个类进行通信
## 主存-编址与计算
### 用例关系
- 存储单元
- 按字编址:存储体的存储单元是字存储单元,即最小寻址单位是一个字
- 按字节编址:存储体的存储单元是字节存储单元;即最小寻址单位是一个字节。
- 包含关系(`<<include>>`):其中这个提取出来的公共用例称为抽象用例,而把原始用例称为基本用例或基础用例系,当可以从两个或两个以上的用例中提取公共行为时,应该使用包含关系来表示它们。
根据存储器所要求的的容量和选定的存储芯片的容量,就可以计算出所需芯片的总数,即:
$$
总片数 = 总容量 / 每片的容量
$$
**例如:若内存地址区间为 4000H ~ 43FFH每个存储单元可存储 16 位二进制数,该内存区域用 4 片存储器芯片构成,则构成该内存所用的存储器芯片的容量是多少?**
表示一个用例包含另一个用例的行为。当一个用例需要调用另一个用例的行为时,可以使用包含关系。例如,一个购物车用例包含了添加商品和删除商品的用例
**解析:** 在计算机中,内存通常是按照地址来寻址的,每个地址对应着一个存储单元。在这个问题中,给定了内存地址区间为 4000H ~ 43FFH其中 H 表示十六进制数
- 扩展关系(`<<extend>>`):如果一个用例明显的混合了两种或两种以上的不同场景,即根据情况可能发生多种分支,则可以将这个用例分为一个基本用例和一个或多个扩展用例,这样使描述可能更加清晰
在十六进制数中,一个数字可以表示 4 位二进制数。因此4000H 表示的二进制数为 010000000000000043FFH 表示的二进制数为 0100001111111111。这两个二进制数之间的差值为 1111111111即 2 的 10 次方减 1也就是 1023
表示一个用例可以扩展另一个用例的行为。当一个用例需要在另一个用例的基础上扩展行为时,可以使用扩展关系。例如:一个支付用例可以扩展一个下单用例,以实现支付功能
因此,该内存地址区间中共有 1024 个存储单元(地址数量),分别对应着 4000H ~ 43FFH 中的每个地址。每个存储单元可以存储一个 16 位二进制数,因此该内存区域的总容量为 1024 x 16 = 16384 位二进制数
- 泛化关系:当多个用例共同拥有一种类似的结构和行为的时候,可以将它们的共性抽象称为父用例,其他的用例作为泛化关系中的子用例。在用例的泛化关系中,子用例是父用例的一种特殊形式,子用例继承了父用例所有的结构、行为和关系
由于该内存所用的存储器芯片数量为 4 片,因此每片存储器芯片的容量为 16384 / 4 = 4096 位二进制数,即 4KB。
用例之间的继承关系表示子类型“是一种”父类型。其中父类型通常是一个 **抽象泛化用例** ,具有子类型共有的属性和行为,每个具体的子类型继承它,并实现适合自己的特定操作。
## 总线
![202305062110211](../../../../../public/img/2023/05/06/202305062110211.gif)
一条总线同一时刻仅允许一个设备发送,但允许多个设备接收。
## 设计模式
总线的分类:
### 设计模式分类
- 数据总线Data Bus在 CPU 与 RAM 之间来回传送需要处理或是需要储存的数据。
- 地址总线Address Bus用来指定在 RAMRandom Access Memory之中储存的数据的地址。
- 控制总线Control Bus将微处理器控制单元Control Unit的信号传送到周边设备一般常见的为 USB Bus 和 1394 Bus。
| | 创建型 | 结构型 | 行为型 | 行为型 |
| ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 类 | factory method <br />工厂方法模式 | adapter<br />适配器模式(类和对象) | template method<br />模板方法模式 | interpreter<br />解释器模式 |
| 对象 | abstract factory抽象工厂模式<br />prototype原型模式<br />singleton单例模式<br />builder构建器模式 | bridge桥接模式<br />composite组合模式<br />decorator装饰模式<br />facade外观模式<br />flyweight享元模式<br />proxy代理模式 | chain of responsibility职责链模式<br />command命令模式<br />iterator迭代器模式<br />mediator中介者模式 | memento备忘录模式<br />observer观察者模式<br />state状态模式<br />strategy策略模式<br />visitor访问者模式 |
## 串联系统与并联系统
### 创建型设计模式应用场景
| 设计模式 | 简要说明 | 速记 |
| ---------------------------------- | ------------------------------------------------------------ | -------------- |
| Factory Method<br />工厂方法模式 | 定义一个创建对象的接口,但由子类决定需要实例化哪一个类。工厂方法使得子类实例化的过程推迟。 | 动态生产对象 |
| Abstract Factory<br />抽象工厂模式 | 提供一个接口,可以创建一系列相关接口或相互依赖的对象,而无需指定它们具体的类。 | 生产成系列对象 |
| Builder<br />构造器模式 | 将一个复杂类的表示与其构造相分离,使得相同的构建过程能够得出不同的表示。 | 复杂对象构造 |
| Prototype<br />原型模式 | 用原型实例指定创建对象的类型,并且通过拷贝这个原型来创建新的对象。 | 克隆对象 |
| Singleton<br />单例模式 | 保证一个类只有一个实例,并提供一个访问它的全局访问点。 | 单实例 |
### 结构型设计模式应用场景
| 设计模式 | 简要说明 | 速记 |
| ----------------------- | ------------------------------------------------------------ | ------------ |
| Adapter<br />适配器模式 | 将一个类的接口转换成用户希望得到的另一种接口。它使原本不相容的接口得以协同工作。 | 转换接口 |
| Bridge<br />桥接模式 | 将类的抽象部分和它的实现部分分离开来,使它们可以独立地变化。 | 继承树拆分 |
| Composite<br />组合模式 | 将对象组合成树型结构以表示“整体-部分”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 | 树形目录结构 |
| Decorator<br />装饰模式 | 动态地给一个对象添加一些额外的职责。它提供了用子类扩展功能的一个灵活的替代,比派生一个子类更加灵活。 | 动态附加职责 |
| Facade<br />外观模式 | 定义一个高层接口,为子系统中的一组接口提供一个一致的外观,从而简化了该子系统的使用。 | 对外统一接口 |
| Flyweight<br />享元模式 | 提供支持大量细粒度对象共享的有效方法。 | 汉字编码 |
| Proxy<br />代理模式 | 为其他对象提供一种代理以控制这个对象的访问。 | 快捷方式 |
### 行为型设计模式应用场景
| 设计模式 | 简要说明 | 速记 |
| ------------------------------------ | ------------------------------------------------------------ | ---------------- |
| Chain of Responsibility 职责链模式 | 通过给多个对象处理请求的机会,减少请求的发送者与接收者之间的耦合。将接收对象链接起来,在链中传递请求,直到有一个对象处理这个请求。 | 传递职责 |
| Command<br />命令模式 | 将一个请求封装为一个对象,从而可用不同的请求对客户进行参数化,将请求排队或记录请求日志,支持可撤销的操作。 | 日志记录,可撤销 |
| Interpreter<br />解释器模式 | 给定一种语言,定义它的文法表示,并定义一个解释器,该解释器用来根据文法表示来解释语言中的句子。 | 虚拟机的机制 |
| Iterator<br />迭代器模式 | 提供一种方法来顺序访问一个聚合对象中的各个元素,而不需要暴露该对象的内部表示。 | 数据集 |
| Mediator<br />中介者模式 | 用一个中介对象来封装一系列的对象交互。它使各对象不需要显式地相互调用,从而达到低耦合,还可以独立地改变对象间的交互。 | 不直接引用 |
| Memento<br />备忘录模式 | 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,从而可以在以后将该对象恢复到原先保存的状态。 | 游戏存档 |
| Observer<br />观察者模式 | 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。 | 联动 |
| State<br />状态模式 | 允许一个对象在其内部状态改变时改变它的行为。 | 状态变成类 |
| Strategy<br />策略模式 | 定义一系列算法,把它们一个个封装起来,并且使它们之间可互相替换,从而让算法可以独立于使用它的用户而变化。 | 多方案切换 |
| Template Method<br />模板方法模式 | 定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重新定义算法的某些特定步骤。 | 框架 |
| Visitor<br />访问者模式 | 表示一个作用于某对象结构中的各元素的操作,使得在不改变各元素的类的前提下定义作用于这些元素的新操作。 | 数据与操作分离 |
## 测试相关
### 测试分类
- 静态测试
- 桌前检查
- 代码走查
- 代码审查
- 动态测试
- 黑盒测试:等价类划分(确定无效与有效等价类,设计用例尽可能多的覆盖有效类,设计用例只覆盖一个无效类)、边界值分析(处理边界情况时最容易出错,选取的测试数据应该恰好等于、稍小于或稍大于边界值)、错误推测、因果图。
- 白盒测试:语句覆盖、判定覆盖、条件覆盖、条件/判定覆盖、路径覆盖
### 白盒测试
| | 定义 | 特点 |
| -------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| 语句覆盖 | 被测试程序中的每条语句至少执行一次。 | 对执行逻辑覆盖很低,一般认为是很弱的逻辑覆盖。 |
| 判定覆盖(分支覆盖) | 被测试程序每个判定表达式至少获得一次“真”值和“假”值(或者程序中每一个判定取“真”分支和取“假”分支至少通过一次)。 | 判定覆盖比语句覆盖更强一些。判定可以是 1 个条件,也可以是多个条件的组合。 |
| 条件覆盖 | 每一个判定语句中每个逻辑条件的各种可能的值至少满足一次。 | 条件覆盖和判断覆盖没有包含关系。 |
| 判断/条件覆盖 | 判定中每个条件的所有可能取值(真/假)至少出现一次,并使每个判定本身的判定结果(真/假)也至少出现一次。 | 同时满足判定覆盖和条件覆盖。 |
| 条件组合覆盖 | 每个判定中的各种可能值的组合都至少出现一次。 | 同时满足判定覆盖、条件覆盖、判定/条件覆盖。 |
| 路径覆盖 | 覆盖被测试程序中所有可能的路。 | |
| 基本路径测试 | 每一条独立路径都执行过(即程序中可执行语句至少执行一次)。 | 测试用例个数与环路复杂度一致。判定为关键控制结点,必须出现在基本路径中。 |
| 循环覆盖 | 循环中每个条件都得到验证。 | 注意数组参数可循环验证。 |
### 特殊的测试阶段及任务
- 验收测试:有效性测试、软件配置审查、验收测试。
- 系统测试:恢复测试、安全性测试、强度测试、性能测试、可靠性测试和安装测试。
- 集成测试:模块间的接口和通信。
- 单元测试:模块接口、局部数据结构、边界条件、独立的路径、错误处理。
- 回归测试:修改软件后进行的测试,防止引入新的错误。
- 负载测试:对软件负载能力的测试。
- 压力测试:对软件超负荷条件下运行情况的测试。
串联系统可靠度:
$$
R = R_1 * R_2 * ... *R_n
$$
并联系统可靠度:
$$
R = 1 - (1 - R_1) * (1 - R_2) * ... * (1 - R_n)
$$
## 附录
@@ -364,7 +456,7 @@ UML 2.0 分为结构图和行为图。
上午《基础知识》考试题型均为 **单选题(客观题)** ,一共 75 道题,总分 75 分,考试采取笔试的方式进行作答,考生在答题卡上进行填涂,考试时长共 150 分钟,其中 71~75 题为英语题。
下午《应用技术》考试题型为 **主观题,涵盖题型较广,包括填空题、问答题、算法设计图补充等** 多种题型。其中包括四道必做题与二道选答题,选答题一般是在 C++ 和 Java 中二选一,前面四道大题一般是结构化分析设计、数据库分析设计、面向对象分析与设计和常用数据结构和算法的掌握情况。考试时长同样为 150 分钟,总分 75 分[^1]。
下午《应用技术》考试题型为 **主观题,涵盖题型较广,包括填空题、问答题、算法设计图补充等** 多种题型。其中包括四道必做题与二道选答题,选答题一般是在 C++ 和 Java 中二选一,前面四道大题一般是结构化分析设计、数据库分析设计、面向对象分析与设计和常用数据结构和算法的掌握情况。考试时长同样为 150 分钟,总分 75 分[^2]。
以下是详细介绍:
@@ -386,9 +478,10 @@ UML 2.0 分为结构图和行为图。
**试题5、6二选一C++ 和 Java**
主要考查对常见设计模式的掌握情况该试题通常会结合一个设计模式实例给出实例描述和类图然后进行程序代码填空有C++和Java两个语言版本二选一[^2]。
主要考查对常见设计模式的掌握情况该试题通常会结合一个设计模式实例给出实例描述和类图然后进行程序代码填空有C++和Java两个语言版本二选一[^3]。
## 参考资料
[^1]: 信管网-中级软件设计师考试题目类型有哪些https://www.cnitpm.com/pm1/108810.html
[^2]: 信管网-软件设计师下午题型有哪些https://www.cnitpm.com/pm1/109480.html
[^1]: 转载的关于 二级制的反码,补码,原码等,筛选过的.https://blog.csdn.net/tunln5288/article/details/97562905
[^2]: 信管网-中级软件设计师考试题目类型有哪些https://www.cnitpm.com/pm1/108810.html
[^3]: 信管网-软件设计师下午题型有哪些https://www.cnitpm.com/pm1/109480.html