Skip to content

软件设计基础

软件设计是将需求规格说明转化为具体的体系结构、模块划分、接口定义和数据结构描述的过程。


一、软件设计概述

1.1 设计阶段划分

阶段别名主要任务
概要设计高层设计/体系结构设计确定总体结构、划分模块、定义接口、选择技术方案
详细设计低层设计/模块设计对每个模块进行功能描述、算法设计、数据结构定义

1.2 设计过程内容

  1. 体系结构设计:确定系统整体框架
  2. 数据设计:定义数据结构和数据库
  3. 接口设计:定义模块间和系统外部接口
  4. 过程设计:设计算法和数据结构

二、软件设计基本原则

2.1 模块化 (Modularity)

定义:将复杂系统分解为若干个功能相对独立、规模适中的模块

优点

  • 降低系统复杂度
  • 提高可理解性
  • 提高可维护性
  • 便于团队协作

2.2 信息隐蔽 (Information Hiding)

定义:将模块的内部实现细节对其他模块隐藏,只暴露有限的接口

优点

  • 减少模块间依赖
  • 提高模块独立性
  • 便于修改和维护

2.3 抽象 (Abstraction)

定义:关注事物的主要特征,忽略次要细节

层次

  • 过程抽象:关注功能,忽略实现
  • 数据抽象:关注数据特性,忽略存储细节

三、内聚与耦合

3.1 内聚性 (Cohesion)

定义:模块内部各元素之间功能相关性的紧密程度

原则:追求高内聚

内聚类型(由低到高)

类型说明内聚程度
偶然内聚模块内元素无实质联系,只是恰好放在一起最低
逻辑内聚元素逻辑相关但功能不同(如所有输入处理放一起)
时间内聚元素在同一时间段执行(如初始化模块)
过程内聚元素按特定顺序执行
通信内聚元素使用相同输入数据或产生相同输出
顺序内聚一个元素的输出作为另一个元素的输入
功能内聚所有元素共同完成一个单一、明确的功能最高

记忆口诀

偶逻时过通顺功
低到高来记心中
功能内聚最理想
设计追求要牢记

3.2 耦合性 (Coupling)

定义:模块与模块之间相互依赖的程度

原则:追求低耦合

耦合类型(由高到低)

类型说明耦合程度
内容耦合一个模块直接访问或修改另一个模块的内部数据最高(最差)
公共耦合多个模块共享全局数据
外部耦合模块共享外部设备或文件
控制耦合一个模块通过传递控制信息影响另一个模块的执行
标记耦合模块间传递记录信息(数据结构)
数据耦合模块间只传递简单数据参数最低(最好)

记忆口诀

内公外控标数
高到低来排队
数据耦合最理想
内容耦合最要避

3.3 内聚耦合综合

目标原则理想状态
内聚尽量高功能内聚
耦合尽量低数据耦合

黄金法则高内聚、低耦合


四、SOLID设计原则

4.1 单一职责原则 (SRP)

Single Responsibility Principle

定义:一个类应该只有一个引起它变化的原因,即只承担一项职责

作用

  • 控制类的粒度
  • 提高类的内聚性
  • 降低复杂性

示例

❌ 错误:User类同时处理用户数据和邮件发送
✅ 正确:User类只处理用户数据,EmailService类处理邮件发送

4.2 开闭原则 (OCP)

Open/Closed Principle

定义:软件实体应该对扩展开放,对修改关闭

含义

  • 增加新功能时,通过添加新代码实现
  • 不修改已有的、经过测试的稳定代码

实现方式

  • 使用抽象和多态
  • 依赖抽象而非具体实现

4.3 里氏替换原则 (LSP)

Liskov Substitution Principle

定义:所有引用基类的地方必须能透明地使用其子类对象

简单理解:子类对象应该能够替换父类对象,且程序行为不变

违反示例

❌ 正方形继承矩形,但设置宽高时行为不一致
✅ 使用接口或组合代替继承

4.4 接口隔离原则 (ISP)

Interface Segregation Principle

定义:客户端不应该被迫依赖于它不使用的方法

原则

  • 接口要小而专一
  • 避免"胖接口"
  • 将大接口拆分成小接口

示例

❌ 错误:IWorker接口包含work()和eat()方法,机器人也要实现eat()
✅ 正确:拆分为IWorkable和IFeedable两个接口

4.5 依赖倒置原则 (DIP)

Dependency Inversion Principle

定义

  • 高层模块不应该依赖于低层模块,两者都应该依赖于抽象
  • 抽象不应该依赖于细节,细节应该依赖于抽象

简单理解:面向接口编程,而不是面向实现编程

示例

❌ 错误:OrderService直接依赖MySQLDatabase
✅ 正确:OrderService依赖IDatabase接口,MySQLDatabase实现该接口

4.6 SOLID原则总结

原则缩写核心思想
单一职责SRP一个类只做一件事
开闭原则OCP对扩展开放,对修改关闭
里氏替换LSP子类可以替换父类
接口隔离ISP接口要小而专一
依赖倒置DIP依赖抽象而非具体

五、其他设计原则

5.1 迪米特法则 (LoD)

Law of Demeter / 最少知识原则

定义:一个对象应该对其他对象有尽可能少的了解

规则

  • 只与直接朋友通信
  • 不要调用"朋友的朋友"的方法

朋友包括

  • 当前对象本身
  • 当前对象的成员变量
  • 方法参数
  • 方法创建的对象

5.2 组合优于继承

定义:优先使用对象组合,而不是类继承来实现代码复用

原因

  • 继承是静态的,组合是动态的
  • 继承破坏封装,组合保持封装
  • 继承会导致类爆炸

六、考试要点

选择题常见考法

  1. 内聚类型判断:给定场景,判断属于哪种内聚类型
  2. 耦合类型判断:给定模块交互方式,判断耦合类型
  3. 设计原则应用:判断代码是否违反某设计原则
  4. 原则特点辨析:区分不同设计原则的含义

典型例题

题1:某模块内的各部分都是在同一时间段内执行,这种内聚属于? 答案:时间内聚

题2:模块A通过参数向模块B传递一个标志,模块B根据标志决定执行流程,这种耦合属于? 答案:控制耦合

题3:哪个原则要求"对扩展开放,对修改关闭"? 答案:开闭原则(OCP)

速记表

概念理想状态最差状态
内聚功能内聚偶然内聚
耦合数据耦合内容耦合

上次更新:

如有转载或 CV 的请标注本站原文地址