软件分析设计与建模(UML)期末复习笔记

目录

1.UML可视化建模基础

1.1 OO(面向对象)

1.2 VM(可视化建模)

1.2.1 可视化建模的四个原则

1.2.2 UML的定义

1.2.3 基于UML开发的特征

1.3 用例模型

1.3.1 用例图

1.3.2 活动图

1.4 交互图

1.4.1 顺序图

1.4.2 通信图

1.5 类图

1.6 状态图

1.7 部署图

1.8 构件图

1.9 VOPC类图

1.10 UML公共机制

1.11 领域模型

2.UML面向对象分析与设计

2.1 最佳实践

2.1.1 六个最佳实践

2.1.2 软件开发过程

2.1.3 RUP的四个阶段

2.1.4 RUP的四个主要里程碑

2.2 需求概述

2.2.1 用例模型

2.2.2 术语表

2.2.3 补充需求

2.3.4 需求工程

2.3.5 候选对象和候选动作

2.3 分析设计概述

2.3.1 输出制品

2.3.2 软件架构

2.3.3 分析设计

2.4 架构分析

2.4.1 架构分析的步骤

2.4.2 典型的分层架构

2.5 用例分析

2.5.1 用例分析的步骤

2.5.2 用例实现(定义/结构/优点)

2.5.3 分析类的三种构造型

2.5.4 评估用例

2.6 识别设计元素

2.6.1 子系统、接口

2.6.2 子系统与包的区别

2.7 识别运行时机制

2.7 识别分布

2.7.1 分布模式

2.7.2 主要步骤

2.8 子系统设计

2.8 类设计

2.9 数据库设计

2.10 软开风险

2.11 四层元建模架构

2.12 领域分析

3.设计原则与模式

3.1 GoF

3.1.1 基本原则

3.1.1.1 开闭原则(Open/Closed Principl, OCP)

3.1.1.2 里氏替换(Liskov Substitution Principle, LSP)

3.1.1.3 接口隔离(Interface Segregation Principle, ISP)

3.1.1.4 依赖倒置(Dependency Inversion Principle, DIP)

3.1.1.5 迪米特法则(Law of Demeter)

3.1.2 常见设计模式

3.1.2.1 建造型

工厂模式(Factory)

抽象工厂(Abstract Factory)

建造者(Builder)

原型(Prototype)

单例(Singleton)

3.1.2.2 结构型

适配器(Adapter)

组合(Composite)

桥接(Bridge)

代理(Proxy)

装饰器(Decorator)

享元(Flywight)

外观(Facade)

3.1.2.3 行为型

职责链(Chain of responsibility)

命令(Command)

策略(Strategy)

状态(State)

备忘录(Memento)

模板(Template)

观察者(Observer)

访问者(Visitor)

中介者(Mediator)

解释器(Interprete)

3.2 GRSP

3.2.1 概述

3.2.2 原则

3.2.2.1 创建者(Creator)

3.2.2.2 信息专家(Information Expert)

3.2.2.3 低耦合(Low Coupling)

3.2.2.4 高内聚(High Cohesion)

3.2.2.5 控制器(Controller)

3.2.2.6 纯粹的虚构(Pure Fabrication)

3.2.2.7 间接(Indirection)

3.2.2.8 保护性变化(Protected Variation)


1.UML可视化建模基础

1.1 OO(面向对象)

面向对象

  1. 类(Class):

    • 类是对象的模板或蓝图,定义了对象的属性(特征)和方法(行为)

  2. 对象(Object):

    • 对象是类的实例,表示一个具体的实体

  3. 封装(Encapsulation):

    • 封装是指将对象的状态(属性)和行为(方法)绑定在一起,并隐藏对象的内部实现细节

    • 通过访问控制(如public、private、protected)来限制对对象内部的直接访问

    • 客户端不需要知道封装里面的细节,拿来直接用即可

  4. 继承(Inheritance):

    • 继承是指一个类(子类)可以继承另一个类(父类)的属性和方法,从而实现代码复用和扩展

  5. 多态(Polymorphism):

    • 多态允许不同的对象以相同的接口(方法)来响应不同的操作

    • 通过方法重载(overloading)和方法重写(overriding)来实现多态性

  6. 关联(Assocation):

    • 关联表示类之间的关系,可以是简单的关联、聚合(Aggregation)或组合(Composition)

OO技术的优势

  1. 提高代码重用性:

    • 通过继承和组合,可以重用已有的类和对象,从而减少代码复用,提高了开发效率

  2. 增强代码可维护性:

    • 封装使得对象的内部实现细节对外部不可见,只暴露必要的接口,从而降低耦合性,增强系统的可维护性

  3. 提高代码灵活性和可扩展性:

    • 多态性允许程序在不修改已有代码的情况下,通过增加新类来扩展系统功能

  4. 自然的建模方式:

    • OO技术通过类和对象来模拟现实世界中的实体和关系,使得系统设计更加直观和易于理解

  5. 增强代码安全性:

    • 通过封装和访问控制,可以保护对象的状态不被外部非法访问和修改,从而提高系统的安全性

  6. 便于团队协作:

    • 明确的类和对象划分,使得不同开发人员可以并行开发不同的类和模块,提高团队协作效率

1.2 VM(可视化建模)

是一种对现实世界系统或概念的简化和抽象,用来表示系统的关键特征和行为。

为什么需要建模

  1. 简化复杂性:现实世界系统往往非常复杂,直接处理所有细节是困难且不切实际的,模型通过抽象和简化,只保留系统的关键部分,使得理解和分析变得更加容易

  2. 沟通和交流:模型提供了一种直观的方式来表达系统设计和需求,便于团队成员、客户和其他利益相关者之间的沟通和交流,确保大家对系统的理解一致

  3. 设计和规划:在开发之前创建模型,可以帮助团队更好地规划系统结构和行为,识别潜在的问题和风险,优化设计方案,提高开发效率和质量

  4. 文档和记录:模型可以作为系统设计和实现的文档,提供详细的设计说明和实现指南,便于后续的维护和扩展

  5. 验证:通过模型,可以提前验证系统设计是否满足需求,检查设计中的逻辑错误和不一致,确保系统在实现之前就已经经过初步验证

  6. 支持自动化和工具使用:现代建模工具可以自动生成代码、文档和测试用例,帮助开发团队提高生产力

1.2.1 可视化建模的四个原则

抽象

  1. 定义:从现实世界中提取出系统的关键特征和行为,而忽略次要或不相关的细节

  2. 原则:

    • 识别关键元素:关注系统中最重要的部分,这些部分对系统功能和行为起着决定性作用

    • 忽略细节:不必要的细节会增加复杂性,应尽量简化模型

    • 层次化建模:通过分层次的方式,逐步细化模型,每一层次都只关注当前层次的细节

  3. 例子:在建模一个银行系统时,可以只关注主要的实体(如客户、帐户、交易),而忽略次要细节(如具体的UI设计)

  4. .客户端需要实现抽象,因此知道的更多

可视化

  1. 定义:可视化是指通过图形、图表或其他视觉表示来展示模型

  2. 原则:

    • 使用标准符号:采用如UML等标准符号来展示模型,确保一致性和易读性

    • 图形化表示:使用图表、图形和颜色等视觉元素,使模型更加直观

    • 简洁明了:避免过于复杂的图形,保持模型的清晰和简洁

  3. 例子:使用UML图来表示系统中的类及其关系

精确性

  1. 定义:指模型必须准确地反映系统的特征和行为,避免歧义和误导

  2. 原则:

    • 明确定义:所有元素和关系必须有明确的定义,确保每个部分都准确反映系统的真实情况

    • 一致性:模型的各个部分必须一致,避免出现冲突或矛盾

    • 细节适度:在必要的地方提供足够的细节,但不过分详细,确保模型的实用性

  3. 例子:在建模中确保每个类的属性和方法准确反映实际系统的需求和功能,避免出现不一致的描述或冗余信息

可验证性

  1. 定义:指模型必须能够被检查和验证,以确保其正确性和完整性

  2. 原则:

    • 验证一致性:通过检查模型的一致性,确保不同部分之间没有冲突

    • 验证完整性:确保模型覆盖了系统的所有关键方面,没有遗漏重要元素和关系

    • 迭代改进:模型应该是可修改和改进的,通过不断和验证,提高模型的准确性和完整性

  3. 例子:在UML工具中,通过自动检查功能验证模型的一致性和完整性,确保所有类、对象和关系都正确无误。

1.2.2 UML的定义

Unified Modeling Language,统一建模语言,是一种用于软件工程的标准化建模语言。它提供了一套图形化表示方法,用于描述、构建和文档化软件的各个方面。

特点

  1. 标准化建模语言:UML是一种标准化的语言,由OMG指定和维护,旨在提供一种通用的表示方式来描述软件系统的结构和行为

  2. 图形化表示:UML使用图形符号和图表来表示系统的各个方面,使得模型更加直观和易于理解。

  3. 面向对象:UML主要用于面向对象系统的建模

  4. 多视角建模:结构视图、行为视图和交互视图。

主要组成部分

  1. 结构图(Structual Diagrams):

    • 类图(Class Diagram):描述系统的类、属性、方法及其相互关系

    • 对象图(Object Diagram):展示系统在某一时刻的对象实例及其关系

    • 组件图(Component Diagram):描述系统的组件及其相互依赖关系

    • 部署图(Deployment Diagram):表示系统的硬件节点及其上部署的软件组件

    • 包图(Package Diagram):组织和分组类和其他模型元素

  2. 行为图(Behavioral Diagrams):

    • 用例图(Use Case Diagram):展示系统的功能需求及其外部用户或系统的交互

    • 活动图(Activity Diagram):表示系统的流程和操作序列

    • 状态图(State Diagram):描述对象的状态及其状态转换

  3. 交互图(Interaction Diagram):

    • 序列图(Sequence Diagram):展示对象之间的交互顺序

    • 通信图(Communication Diagram):表示对象之间的通信路径

    • 时间图(Timing Diagram):描述对象状态或属性随时间变化的情况

    • 交互概览图(Interaction Overview Diagram):综合展示系统交互的概览

1.2.3 基于UML开发的特征

基于UML的开发过程具有三个显著的特征:用例驱动、以架构为中心和迭代开发,这些特征共同构成了一种系统化的方法,确保软开过程的结构化和高效性

用例驱动

定义:用例驱动是指开发过程从用例出发,通过识别和定义用例来驱动系统的分析、设计、实现和测试

特点:

  • 需求捕获:用例描述了系统如何与外部用户(或其他系统)交互,从而捕获了系统的功能需求

  • 用户视角:用例反映了用户的视角和需求,确保系统最终能够满足用户的需求

  • 可追溯性:通过用例,可以追踪需求的实现过程,确保每个用户在设计、实现和测试中都得到关注

优势:

  • 清晰的需求描述:用例提供了一种简单明了的方式来描述系统需求,使得需求沟通更加顺畅

  • 用户参与:用例可以直观地展示系统功能,方便用户参与需求定义和验证过程

  • 指导设计和测试:用例驱动设计和测试,使得开发过程始终围绕需求展开,确保功能完整性和一致性

以架构为中心

定义:以架构为中心是指开发过程中的各个阶段都围绕系统架构进行,系统架构是系统的核心,并指导详细设计和实现

特点:

  • 架构视图:系统架构通过多个视图(如逻辑视图、开发视图、过程视图和物理视图)来描述,提供了系统的全局视角

  • 架构基线:在项目早期阶段确定系统架构,并在整个开发过程中保持架构的一致性和稳定性

  • 架构驱动设计:详细设计和实现基于系统架构展开,确保系统各部分协调一致

优势:

  • 全局视角:以架构为中心的方法确保开发团队对系统的全局有清晰的理解,有助于做出合理的设计决策

  • 一致性:系统架构作为统一的蓝图,指导各个子系统和组件的开发, 确保整体一致性和协调性

  • 可维护性和扩展性:良好的架构设计有助于系统的可维护性和扩展性,为未来的改进和扩展提供基础

迭代开发

定义:将开发过程分为多个短周期,每个迭代都是一个完整的开发周期,包括需求分析、设计、实现和测试

特点:

  • 增量交付:每个迭代都交付一个可运行的系统版本,逐步增加系统功能

  • 快速反馈:通过频繁的迭代和交付,开发团队能够即使获得用户和利益相关者的反馈,进行调整和改进

  • 风险管理:迭代开发可以早期识别和解决问题,降低项目风险

优势:

  • 灵活应变:迭代开发允许开发团队在每个迭代结束时评估和调整计划,应对需求变化和技术挑战

  • 用户满意度:通过持续交付可用的系统版本,用户能够早期看到和使用系统,提高满意度和参与度

  • 持续改进:每个迭代都提供了改进的机会,开发团队可以逐步优化系统功能和性能。

1.3 用例模型

用于描述系统功能与外部用户或外部系统之间交互的模型。它主要关注"谁"(参与者)在使用“什么”(用例)功能。用例模型是系统需求分析阶段的重要工具,帮助确定和传达系统需求——系统行为

1.3.1 用例图

主要元素

  1. 参与者(Actor):参与者是与系统交互的外部实体,可以是用户 、人、组织、硬件设备或其他系统。参与者可以分为:

    • 主要参与者(Primary Actor):直接使用系统功能的实体

    • 次要参与者(Secondary Actor):辅助系统完成某些功能的实体,不直接使用系统

  2. 用例(Use Case):用例是系统执行的一组活动或操作,旨在为一个或多个参与者提供可观的结果,用例通常表示系统的一个功能或需求

关系:

  1. 参与者与用例的关系:参与者与用例之间的关系通常是”关联关系“,表示参与者参与用例的执行。关系通常用实线表示,线的一端连接参与者,另一端连接用例。

  2. 用例之间的关系:

    • 包含(Include):一个用例包含另一个用例的功能,常用于提取用例的公共功能

    • 扩展(Extend):一个用例可以在特定条件下扩展另一个用例的功能。常用于描述可选行为

    • 泛化(Generalization):一个用例是另一个用例的特例,表示子用例继承父用例的行为

用例图:描述系统功能和外部用户或外部系统之间的交互,展示actor、use case之间的关系

  1. 基本组成:

    • 椭圆表示用例

    • 小人或矩形表示参与者

    • 实线表示关联关系

    • 虚线和​标注表示包含和扩展关系

用例描述:是对用例的详细文字说明,通常包括以下部分:

  • 用例名称

  • 参与者

  • 前置条件:用例执行前系统必须满足的条件

  • 后置条件:用例执行后系统的状态

  • 主事件流:执行用例的基本步骤

  • 替代事件流:用例执行过程中可能出现的替代步骤

1.3.2 活动图

描述用例内部流程和逻辑的一种图。在UML中,活动图类似于流程图,主要用于表示业务流程或操作步骤,展示系统在某一用例或场景中的行为状态。

通过活动图,可以清楚地看到用例的执行过程及其设计的各个活动、决策点和流向

基本元素:

  1. 活动(Activity):表示系统执行的一个步骤或动作,通常用矩形框表示

  2. 活动状态(Activity State):活动图中的一个步骤,代表系统在执行某个动作时的状态

  3. 控制流 (Control Flow):表示活动之间的执行顺序,用箭头连接不同的活动状态

  4. 分支(Decision):用于表示流程中的决策点,根据条件选择不同的路径。分支点用菱形表示,路径上标注条件

  5. 合并(Merge):表示来自不同路径的控制流合并到一起,用菱形表示

  6. 开始节点(Initial Node):表示活动流程的起点,用填充的圆形表示

  7. 结束节点(Final Node):表示活动流程的终点,用带圆圈的填充圆形表示

  8. 并行分叉(Fork)和并行合并(Join):

    • Fork:表示并行执行的多个活动,用一条水平或垂直线表示

    • Join:表示并行执行的多个活动的合并,用一条水平或垂直线表示

1.4 交互图

Interaction Diagram用于描述系统中对象或组件之间的交互,展示它们之间的信息交换和控制流——动态行为。交互图主要有两种类型:顺序图(Sequence Diagram)和通信图(Communication Diagram),通信图也叫做协作图(Collaboration Diagram)。

交互图的作用:

  • 描述动态行为:交互图用来描述系统中对象之间的动态行为和信息交换,展示系统的运行过程

  • 明确对象职责:通过交互图,可以明确系统中各个对象的职责和协作关系,有助于理解系统的设计和实现

  • 支持需求分析和设计:交互图在需求分析和设计阶段起到重要作用,帮助建模系统的功能和行为

  • 验证和调试:交互图可以用于验证系统设计的正确性,以及在调试过程中帮助发现和解决问题

1.4.1 顺序图

顺序图强调消息的时间顺序,用来表示对象之间按时间顺序发生的交互。它可以清晰地显示系统中对象之间的调用关系以及调用顺序。

主要元素:

  • 执行者实例:表示系统外部与系统交互的实体,通常是用户、外部系统、硬件设备等

  • 对象(Object):用矩形表示,位于图的顶部,包含对象的名称和类名

  • 生命线(Lifeline):用虚线表示,从对象符号向下延伸,表示对象在时间维度上的存在

  • 激活(Activation):用细长的矩形表示,绘制在生命线上,表示对象在某段时间内执行某个操作

  • 消息(Message):用箭头表示,箭头从一个对象的生命线指向另一个对象的生命线,表示消息的传递。分为同步消息 (实线箭头)和异步消息(虚线箭头)。消息是被调用对象的操作,拿下面举例,用户登录时被调用的系统进行用户登录,而不是用户进行登录,因此消息是被调用对象的操作

  • 返回消息(Return Message):用虚线箭头表示,表示操作执行后的返回结果

1.4.2 通信图

通信图(以前称协作图)强调对象之间的结构关系,用来表示对象之间的消息传递和连接方式。它展示的是对象如何相互连接以及在这些连接上发生的消息交换

主要元素:

  • 执行者实例:表示系统外部与系统交互的实体,通常是用户、外部系统、硬件设备等

  • 对象(Object):用矩形表示,包含对象的名称和类名

  • 连接(Link):用线条表示,连接不同的对象,表示对象之间的关联关系

  • 消息(Message):用标注在连接线上的数字和箭头表示,表示消息的传递顺序和方向

1.5 类图

用于描述系统中的类、接口及其之间关系的静态结构图。类图展示了系统中的类的结构,包括它们的属性、方法及类之间的各种关系,是面向对象建模的重要工具

基本元素:

  1. 类:类是类图的核心元素,表示具有相同属性和方法的对象集合。类用矩形表示,分为三部分:

    • 类名(Class Name):显示在矩形的顶部

    • 属性(Attributes):显示在矩形的中部,表示类的特征

    • 方法(Operations):显示在矩形的底部,表示类的行为

  2. 接口:表示类或组件的一组操作规范,接口也用矩形表示,但通常在矩形顶部使用​标注

  3. 关系(Relationships):

    • 关联(Association):表示类之间的结构关系,用实线表示。可以在关联线上加上角色名、导航箭头和多重性(如1、0..*)

    • 泛化(Generalization):表示类之间的继承关系,用空心三角箭头的实线表示,箭头指向父类

    • 实现(Realization):表示类实现接口的关系,用空心三角箭头的虚线表示,箭头指向接口

    • 依赖(Dependency):表示一个类依赖于另一个类,用虚线箭头表示,箭头指向被依赖的类

    • 聚合(Aggregation):表示整体和部分的关系,用空心菱形和实线表示,菱形指向整体

    • 组合(Composition):表示整体与部分的强关系,用实心菱形和实线表示,菱形指向整体,整体和部分的生命周期是一样的, 整体亡,部分亡

类图的作用

  • 描述系统结构:类图展示了系统中的类及其属性、方法和相互关系,帮助理解系统的静态结构

  • 支持面向对象设计:类图帮助进行面向对象的系统设计,定义类及其职责,促进代码的组织和重用

  • 促进沟通和协作:类图作为系统设计的可视化工具,促进团队成员之间的沟通和协作,确保对系统结构的共识

分析场景中的业务实体(Business Entity)步骤:

  1. 理解业务场景:仔细阅读和理解业务场景的描述,识别出关键的活动和交互

  2. 识别名词和动词:从描述中提取名词和动词

  3. 识别业务实体:确定哪些名词代表业务实体

  4. 定义属性和行为:对每个业务实体,确定其关键属性和行为

  5. 识别关系和多样性:关系包括关联、聚合、组合等,多样性指的是关系的数量(一对一、一对多、多对多)

1.6 状态图

State Diagram也称为状态机图(State Machine Diagram),用于描述对象或系统在其生命周期中的不同状态及状态之间的转换。状态图特别适用于建模具有复杂状态变化的系统或对象,例如协议、工作流和嵌入式系统

基本元素

  1. 状态(State):表示对象在某个时刻所处的条件或情形。状态用圆角矩形表示,内部写上状态的名称

  2. 初始状态(Initial State):表示状态机的起始点,用实心圆表示

  3. 终止状态(Final State):表示状态机的结束点,用带外圈的实心圆表示

  4. 转换(Transition):表示对象从一个状态到另一个状态的变化,用带箭头的线表示。箭头从源状态指向目标状态

  5. 事件(Event):触发状态的条件或动作,通常标注在转换箭头旁边

  6. 条件(Guard):是对事件的附加限制,只有当条件满足时,状态转换才会发生,条件用方括号表示,写在事件的后面

  7. 动作(Action):在状态转换发生时执行的操作,通常用斜杠"/"表示,写在事件或条件后面

作用:

  • 描述对象行为:状态图展示了对象在其生命周期中可能经历的状态和状态之间的转换,帮助理解对象的动态行为

  • 支持复杂系统建模:对于具有复杂状态变化的系统,状态图提供了一种直观的建模方式,是设计和分析更加清晰

  • 促进需求分析和设计:状态图在需求分析和系统设计阶段起到重要作用,帮助识别和定义系统的状态和行为

  • 验证系统逻辑:通过状态图,可以验证系统设计的逻辑正确性,确保状态转换的完整性和一致性

1.7 部署图

Deployment Diagram用于描述系统的硬件和软件部署结构,展示系统在运行时的物理配置。部署图帮助理解和规划系统的物理架构,包括节点、设备、组件以及它们之间的关系

基本元素:

  1. 节点(Node):表示物理设备或运行时的计算资源,通常是计算机、服务器、移动设备等,用立方体表示,内部可以包含部署在该节点上的组件或对象

  2. 组件:表示系统中的可部署的模块化单元,如软件模块、数据库等。组件用矩形表示,通常在矩形的左上角带有一个小矩形图标

  3. 部署:表示组件在节点上的安装或执行关系,用带箭头的实线表示,箭头指向部署的目标节点

  4. 关联:表示节点之间的通信路径或连接,用实线表示

  5. 制品(Artifact):表示开发过程中产生的物理文件,如可执行文件、库文件、配置文件等。用矩形表示,并可以与组件相关联

可以用矩形表示组件并部署到对应的节点上(用带箭头的实线表示)

作用:

  • 描述系统的物理架构:展示了系统在运行时的物理部署结构,帮助理解系统的硬件和软件配置

  • 支持系统规划和实时:部署图在系统规划话和实施阶段起到重要作用,帮助确定各个组件的部署位置和部署方式

  • 优化系统性能和可靠性:通过部署图,可以分析系统的物理架构,优化系统的性能和可靠性

  • 促进团队沟通和协作:部署图作为系统设计和实施的可视化工具,促进团队成员之间的沟通和协作

1.8 构件图

Component Diagram用于描述系统中的组件及其之间的关系。构件图展示了系统中各个构建的物理实线,构件之间的依赖关系以及构件内部的接口和提供的服务,是系统实现视图的一部分

基本元素:

  1. 构件:系统中的物理和逻辑单元,表示系统中的可替换的模块。构建用带有两个小矩形图标的矩形表示

  2. 接口:接口是构件提供或使用的服务规范,表示构件间的交互契约。接口有两种表示方法:

    • 提供接口:用圆圈表示,圆圈连接到提供接口的构件

    • 使用接口:用半圆(也称为'socket')表示,半圆连接到使用接口的构件

  3. 依赖关系:表示一个构件依赖于另一个构件,通常是使用其提供的接口。依赖关系用带箭头的虚线表示,箭头指向被依赖的构件

  4. 实现关系:表示构件实现了某个接口,实现关系用带空心箭头的虚线表示,箭头从构件指向接口

  5. 端口:是构件与外界进行交互的接入点,用小矩形表示,通常在构件的边缘

作用:

  • 描述系统的模块化结构:展示了系统的物理模块及其相互关系,帮助理解系统的模块化设计

  • 支持系统实现和部署:在系统实现和部署阶段起到重要作用,帮助确定各个模块的实现和部署方式

  • 促进系统可维护性和可扩展性:通过清晰的模块化设计,构件图支持系统的可维护性和可扩展性。

1.9 VOPC类图

View of Participating classes 参与类图是简化的类图,强调类之间的关系而不用详细写出类的属性与方法,VOPC只有关联关系

示例:

1.10 UML公共机制

扩展机制:允许用户通过定义心的建模元素来扩展UML语言,以满足特定领域或问题的需求。主要的扩展机制包括:

  • 新的建模元素:用户可以定义新的类、关系、图形符号或其他UML元素,这些新元素可以扩展UML的基础元模型,增强模型的表达能力和适用性

  • 建模扩展机制(Modeling Extension Mechanisms):包括使用UML的Profile和Stereotype来扩展和定制UML模型。Profile是一组模型元素和关系的集合,它们定义了一种特定领域的UML扩展。Stereotype是一种Profile中的定制标签,用于给UML元素赋予特定的语义或行为

构造型(Metamodeling):是一种元模型的建立和应用,它允许用户定义新的元素类型和它们之间的关系。在UML中共,元模型描述了UML本身的语法和语义规则,而构造性允许用户扩展或定制这些规则。通过构造型,用户可以:

  • 定义新的建模元素类型:如定义新的类别,接口、关系类型等

  • 扩展现有的元模型:在不改变UML语言核心定义的前提下,添加额外的元素和语义

约束(Constraints):是对模型元素进行进一步限制或说明的规则或条件。在UML中,可以使用自然语言、OCL(Object Constraint Language)或其他形式来定义。约束可以应用于类、属性、关系等不同的建模元素,以确保模型的正确性和一致性

  • 形式约束(Formal Constraints):使用OCL表达式定义的约束,可以检查模型中属性的取值范围、关系的条件等

  • 语义约束(Semantic Constraints):描述模型中元素之间的语义关系和约束,如业务规则、操作的前置条件和后置条件等

标记值(Tagged Values):是UML元素的自定义属性或附加信息,用于扩展UML元素的描述和语义。标记值允许用户在UML元素上添加额外的元数据或属性,以提供更加丰富的信息

  • 自定义属性(Custom Properties):将特定于应用程序或领域的信息与UML元素关联,如版本信息、作者、创建日期等

  • 元数据扩展(Metadata Extension):使用标记值可以在UML模型中引入特定于应用程序或领域的元数据,帮助在开发过程中管理和维护模型

1.11 领域模型

领域模型被描述为一组没有定义操作的类图,可以有属性。类之间的关系一般只有关联

2.UML面向对象分析与设计

OOA/D(面向对象分析与设计文档) 指的是用于记录和表达面向对象分析与设计过程中产生的各种文档和图表。这些文档和图表用于捕捉系统需求、设计方案和系统架构、帮助团队成员和利益相关者理解和沟通系统的结构和行为

主要的OOA/D Artifacts包括:

  • 需求文档

  • 用例模型

  • 类图

  • 活动图

  • 状态图

  • 序列图和协作图

  • 部署图和组件图

  • 设计文档

2.1 最佳实践

2.1.1 六个最佳实践

迭代开发(Develop Iteratively):

  1. 概念:是一种增量式的软件开发方法,每个迭代周期包含规划、设计、实现和测试。每个迭代通常持续2-4周,目的是逐步改进和完善软件系统

  2. 关键点

    • 反馈循环:每个迭代结束时,收集用户和团队的反馈以改进下一个迭代

    • 渐进交付:逐步交付可用的产品版本,而不是一次性交付最终版本

    • 风险管理:通过早期和频繁的交付,识别和解决风险

管理需求(Mange requirements):

  1. 概念:指收集、分析、记录和追踪系统需求的过程。需求管理确保所有利益相关的需求都得到识别并在开发过程中得到考虑

  2. 关键点:

    • 需求捕获:使用UML用例图来捕获和描述系统需求

    • 需求分析:评估需求的可行性、优先级和影响

    • 需求追踪:通过工具和文档跟踪需求的实现情况和变更

使用基于构件的架构(Use componet-based architectures):

  1. 概念:是一种软件设计方法,通过将系统划分为独立的构件,这些构件可以被单独开发、替换和重用

  2. 关键点:

    • 模块化:将系统划分为可管理的构件,以便独立开发和测试

    • 重用性:构件可以在不同的系统中重用,减少开发时间和成本

    • 接口设计:使用UML类图和组件图定义构件的接口和交互

可视化建模(Model the software visually):

  1. 概念:使用UML图表来描述系统的结构、行为和交互。这有助于团队理解和沟通复杂的系统设计

  2. 关键点:

    • 沟通工具:使用UML图表和类图、顺序图和状态图来提高团队沟通和协作

    • 设计验证:通过可视化模型验证设计的一致性和完整性

    • 文档生成:自动生成系统文档,确保文档与实现保持同步

持续验证质量(Continuously verify quality):

  1. 概念:指在开发过程的每个阶段不断测试和验证系统,以确保其符合质量标准和需求

  2. 关键点:

    • 测试驱动开发(TDD):在编写代码前先编写测试用例

    • 自动化测试:使用工具进行自动化单元测试、集成测试和系统测试

    • 代码审查和静态分析:定期进行代码审查和静态代码分析,发现并修复问题

管理变更(Control Changes):

  1. 概念:指识别、评估、批准、实施和追踪系统变更的过程。有效地变更管理确保系统的稳定性和质量

  2. 关键点:

    • 版本控制:使用版本控制系统(如Git)来管理代码和文档的变更

    • 变更请求:使用变更请求(CR)流程记录和追踪变更

    • 影响分析:评估变更对系统的影响,包括成本、时间和风险

2.1.2 软件开发过程

指将软件需求转化为工作软件的系统性活动序列,它涉及多个步骤和活动,从初始需求获取到软件的部署和维护

Who:

  • 利益相关者:客户、用户、业务分析师、项目经理

  • 开发团队:软件开发人员、架构师、测试人员、UI/UX设计师、DevOps工程师

  • 支持团队:技术支持、运维人员、数据库管理员

What:

  • 需求收集:获取并分析软件的功能和非功能需求

  • 设计:创建系统架构和详细设计

  • 实现:编写代码并集成不同模块

  • 测试:验证软件的功能和性能,确保符合需求

  • 部署:将软件发布到生产环境中

  • 维护:修复缺陷并实施必要的改进

When:

  • 项目启动:项目立项,请求收集

  • 开发阶段:系统设计和实现

  • 测试阶段:系统测试和验收测试

  • 部署阶段:软件发布

  • 维护阶段:后续支持和维护

How:

  • 项目管理方法:如瀑布模型、敏捷方法(Scurm, Kanban)

  • 工具和技术:版本控制系统(如Git)、CI/CD工具(如Jenkins)、开发框架和库

  • 协作工具:Jira、Trello、Slack、Confluence

  • 质量保证:代码审查、单元测试、集成测试、系统测试、用户验收测试

2.1.3 RUP的四个阶段

RUP(Rational Unified Process, 统一软件开发过程)是一个面向对象和基于迭代开发过程框架。它将开发过程分为四个阶段:

  1. 初始阶段(Inception):

    • 目标:确定项目的商业可行性,定义项目范围和初步需求

    • 活动:需求获取、初步用例建模、风向分析、项目计划

    • 成果:项目愿景文档、初步用例模型、风险列表、项目计划

  2. 细化阶段(Elaboration):

    • 目标:细化系统架构,减少主要风险,完成大部分需求分析

    • 活动:详细用例建模、系统架构设计、关键原型开发、风险缓解

    • 成果:详细用例模型、系统架构文档、原型、修订后的项目计划

  3. 构造阶段(Construction):

    • 目标:完成系统设计和实现,开发所有功能并进行集成

    • 活动:详细设计、代码实现、单元测试、集成测试

    • 成果:完整的系统、测试报告、用户文档

  4. 移交阶段(Transition):

    • 目标:进行beta测试和部署

    • 活动:系统部署、用户培训、验收测试、缺陷修复

    • 成果:已部署的系统、用户培训材料、验收测试报告

2.1.4 RUP的四个主要里程碑

RUP定了了四个主要里程碑(Milestones),用于评估项目进展和决定是否进入下一个阶段:

  1. LCO(Lifecycle Objectives) 生命周期目标:

    • 位置:初始阶段技术

    • 目标:验证项目的目标和范围是可行的,并且主要风险已被识别和评估

    • 成果:通过LCO评审,批准进入细化阶段

  2. LCA(Lifecycle Architecture) 生命周期架构

    • 位置:细化阶段结束

    • 目标:验证系统的架构设计是稳定的,并且关键风险已被缓解

    • 成果:通过LCA评审,批准进入构造阶段

  3. IOC(Initial Operational Capability) 初始操作能力

    • 位置:构造阶段结束

    • 目标:验证系统的功能是完整的,质量是可接受的,并且系统可以进行初步操作

    • 成果:通过IOC评审,批准进入移交阶段

  4. Release

    • 位置:移交阶段结束

    • 目标:验证系统已经准备好发布到生产环境,并且用户接受该系统

    • 成果:通过Release评审,批准系统发布

2.2 需求概述

在需求分析阶段,UML产生的主要制品包括:

  1. 用例模型(Use Case Model)

  2. 术语表(Glossary)

  3. 补充需求(Supplementary Requirements)

2.2.1 用例模型

由用例图和用例描述组成

用例图:是系统功能的图形化表示,显示了系统中的 Actors和用例之间的关系

  • Actors:系统外部与系统交互的实体,可以是用户、其他系统或硬件设备

  • Use Cases:系统执行的功能或服务,满足某个参与者的特定需求

  • 关系:用例图中的关系包括关联、泛化(继承)、include和extend

用例描述:详细说明每个用例的行为

  • 用例名称:简要描述用例的功能

  • 参与者:涉及到主要和次要参与者

  • 前置条件:用例开始前必须满足的条件

  • 后置条件:用例完成后系统应达到的状态

  • 主成功场景:详细的步骤,描述用例的正常执行流程

  • 替代路径:描述在特殊条件下的替代流程

  • 扩展点:用例的变体或扩展情况

2.2.2 术语表

术语表是定义系统中使用的术语和概念的文档,确保项目团队和利益相关者对关键术语的理解一致

术语表通常包括:

  • 术语:待定义的词或短语

  • 定义:术语的详细解释和描述

  • 示例:如果需要的话

2.2.3 补充需求

是系统功能需求之外的其他需求,包括非功能需求和约束条件,涉及:

  • 性能:系统的响应时间、吞吐量、资源使用等

  • 安全性:数据保护、访问控制、身份验证等

  • 可用性:系统的正常运行时间、故障恢复等

  • 可维护性:系统的可修改性、扩展性、测试性等

  • 接口:与其他系统或硬件的接口要求

  • 法律和监管:遵循法律法规和行业标准

2.3.4 需求工程

是软件工程的一个关键领域,涉及识别、分析、记录、验证和管理软件系统需求的系统化过程。它的目的是确保软件系统能够满足用户和其他利益相关者的需求和期望。

主要阶段:

  • 需求获取(Elicitation):这一阶段目的是从用户和其他利益相关者那里收集需求,活动:

    • 利益相关者识别:确定谁是系统的用户和利益相关者

    • 需求收集方法:适用访谈、问卷调查、研讨会、观察、原型设计等

    • 需求文档:将收集的需求记录在文档中,确保所有利益相关者都能得到理解和认可

  • 需求分析(Aanlysis):在这一阶段,需求被详细分析,以确保其可行性、完整新和一致性

    • 需求分类:将需求分为功能性需求和非功能性需求

    • 需求优先级:确定哪些需求是最重要的,那些需求可以稍后实现

    • 冲突解决:解决不同利益相关者需求之间的冲突

    • 需求建模:使用模型表示需求

  • 需求规格说明:这一阶段将需求详细地记录在需求规格说明书(SRS)中,SRS应包括:

    • 功能性需求

    • 非功能性需求

    • 约束:描述系统开发和运行的限制条件

  • 需求验证:这一阶段目的是确保需求是正确的、完整的、可行的,并且得到了所有利益相关者的认可。活动:

    • 需求评审:通过评审会议,走查等方法验证需求文档

    • 原型验证:使用原型来验证需求是否满足用户的期望

    • 一致性检查:确保需求之间没有冲突,并且需求与系统目标一致

  • 需求管理:是一个持续的过程,贯穿整个软开生命周期,确保需求的变更得到有效管理

    • 需求变更管理:记录和管理需求变更,确保所有变更都有合理的理由,

    • 需求跟踪:跟踪需求从提出到实现的整个过程

    • 需求状态报告:定期报告需求的状态,确保项目团队和利益相关者了解需求的实现进展

2.3.5 候选对象和候选动作

候选对象:指在系统使用场景中提到的,对系统功能和流程有意义的实体和概念。这些对象通常是名词,是系统需要处理、跟踪或管理的内容。候选对象是系统中的静态部分,用于描述系统的状态和属性

候选动作:是指在系统使用场景中涉及的、系统需要执行的功能或操作。这些动作通常是动词,是系统的动态部分,用于描述系统的行为和交互。候选动作反映了系统如何响应用户的操作和输入

2.3 分析设计概述

2.3.1 输出制品

在分析设计阶段,输出制品主要包括:

  1. 设计模型(Design Model)

  2. 架构文档(Architecture Documentation)

  3. 数据模型(Data Model,通常是可选的)

设计模型:是对系统结构和行为的详细描述,包括:

  • 类图

  • 对象图

  • 顺序图

  • 协作图

  • 状态图

  • 活动图

架构文档:是对系统架构的全面描述,包括:

  • 系统概述:系统的背景、目标和范围

  • 架构视图:系统的各个视图及其关系

  • 设计原则:系统设计所遵循的原则和约束

  • 组件说明:系统组件及其职责

  • 接口说明:系统内部和外部接口的详细描述

数据模型:描述系统的数据结构,包括:

  • 实体关系图(ERD):描述实体及其关系

  • 数据库设计:表结构、主键、外键、索引等

2.3.2 软件架构

概述:是系统的高层结构,描述了系统的主要组件及其相互关系。它定义了系统的组织方式、交互机制和设计原则,是系统设计和实现的基础

软件架构的”4+1“视图

  1. 用例视图(Use Case View):描述系统的功能需求和系统对外的行为,基于用例模型,主要面向用户和需求分析师【用例视图就是那个1】

  2. 逻辑视图(Logical View):描述系统的主要设计元素及其关系,主要关注系统的功能需求。它通常包括类图和对象图,面向分析者、设计者

  3. 开发视图(Development View):也称实现视图,描述系统在开发环境中的静态组织结构,主要关注模块和组件的组织及其版本控制。它通常包括组件图和包图,面向编程者

  4. 过程视图(Process View):描述系统的动态行为,特别是运行时的并发性、同步性和分布性。它通常包括活动图和顺序图,面向系统迭代器

  5. 部署视图 (Deployment View):描述系统在物理环境中的部署结构,主要关注硬件节点及其链接关系。它通常包括部署图,面向系统工程

2.3.3 分析设计

分析设计过程中包含的主要活动:

  1. 需求分析:识别并描述系统需求,创建用例模型

  2. 系统设计:定义系统的高层结构和主要组件,创建架构文档

  3. 详细设计:详细描述系统的各个模块和组件,创建设计模型

  4. 数据设计:设计系统的数据结构和数据库模型

  5. 验证:确保设计模型符合需求,进行模型评审和验证

分析和设计的区别:分析和设计是软件开发过程中的两个不同阶段

  • 分析:

    • 目标:了解和描述系统需求

    • 活动:需求获取,用例建模、需求分析

    • 输出:需求文档、用例模型、功能需求说明

  • 设计:

    • 目标:定义系统的结构和行为,实现需求

    • 活动:系统架构设计、详细设计、数据建模

    • 输出:设计模型、架构文档、数据模型、设计说明

2.4 架构分析

架构分析是软件开发过程中的一个关键活动, 用于确定系统的整体结构和高层设计决策。这一过程设计识别系统的主要组件及其交互方式,确保系统能够满足功能和非功能需求

2.4.1 架构分析的步骤

定义设计模型的高层逻辑结构:

  1. 步骤:

    • 创建高层设计模型:利用UML类图、组件图等,描绘系统的主要模块和它们之间的关系

    • 确定模块职责:定义每个模块的职责和功能

    • 划分系统边界:确定系统的边界和外部系统或用户的交互点

  2. 输出:

    • UML类图:显示系统中的类及其关系

    • UML组件图:展示系统的主要组件和它们之间的依赖关系

识别分析机制:

  1. 步骤:

    • 确定关键机制:识别系统中需要解决的共性问题和机制,如持久性、安全性、通信机制等

    • 定义机制实现方法:详细描述这些机制如何在系统中实现

  2. 输出:

    • UML序列图或活动图:展示这些机制在运行是的行为

    • 机制文档:详细描述各个机制的设计和实现方法

识别关键抽象:

  1. 步骤:

    • 识别系统中的核心概念:找出系统中的主要实体和抽象概念

    • 定义这些抽象的职责和关系:明确这些抽象如何协同工作

  2. 输出:

    • UML类图:展示这些关键抽象及其关系

    • 文档:描述每个抽象的职责和行为

2.4.2 典型的分层架构

分层架构是一种常见的软件架构模式,将系统划分为若干层,每一层具有特定的职责,彼此之间通过定义良好的接口进行交互

典型分层架构的层次:

  1. 表示层(Presentation Layer):

    • 职责:处理用户交互,展示数据,并将用户输入传递到业务逻辑层

    • 组件:用户界面组件(UI)、视图(View)、控制器(Controller)

  2. 业务逻辑层(Businnes Logic Layer):

    • 职责:处理具体的业务规则和逻辑,进行数据处理和计算

    • 组件:业务逻辑组件、服务层

  3. 数据访问层(Data Access Layer):

    • 职责:与数据库或其他存储系统交互,进行数据的读写操作

    • 组件:数据访问对象(DAO)、仓储(Repository)

  4. 数据库层(Database Layer):

    • 职责:存储数据,提供数据的持久化机制

    • 组件:数据库管理系统 (DBMS)、数据表、索引

UML表示:

  1. 类图:

    • 表示层类图:展示视图、控制器及其关系

    • 业务逻辑层类图:展示业务逻辑类及其相互关系

    • 数据访问层类图:展示数据访问对象及其业务逻辑层的关系

  2. 组件图:

    • 展示各层组件及其依赖关系

  3. 序列图:

    • 展示不同层之间的交互过程,例如用户请求从表示层到业务逻辑层,再到数据访问层的过程

2.5 用例分析

用例分析是软件开发过程中的一个关键的活动,旨在通过对用例的详细分析,确定系统需要实现的功能和行为。用例分析帮助开发团队明确系统需要完成的任务,并未后续的设计和实现提供基础

2.5.1 用例分析的步骤
  1. 构造每个用例实现:通过交互图和VPOC(Verification of Preconditions and Conditions) 详细描述每个用例的实现过程

  2. 统一分析类:确定分析类并在系统中实现它们,以支持用例的功能

步骤:

  1. 补充用例描述

  2. 对于每个用例实现

    1. 从用例行为中找到类

    2. 将用例行为分发给类

  3. 对于每个结果分析类

    1. 描述职责

    2. 描述属性和关联

    3. 资格分析机制

  4. 统一分析类

  5. 检查点

交互图:包括顺序图和通信图,用于描述用例实现过程中对象之间的动态交互

  • 顺序图:展示对象之间按时间顺序发生的交互,适合描述复杂的消息传递和调用顺序

  • 通信图:展示对象之间的协作和交互,适合展示对象的静态关系和通信

VPOC:

  • 验证前提条件和条件:确保在用例开始执行之前满足特定条件,并在用例执行过程中验证这些条件是否得到满足

    • 前提条件:用例开始前必须满足的条件

    • 后置条件:用例完成后系统必须达到的状态

2.5.2 用例实现(定义/结构/优点)

定义:指将用例中定义的功能和行为转换为具体的系统实现,包括具体的类和对象及其交互

结构:

  • 参与者(Actors):外部与系统交互的用户或系统

  • 用例 (Use Cases):系统提供的功能或服务

  • 分析类:实现用例功能的类,包括边界类、实体类和控制类

优点:

  • 清晰的需求描述:通过用例实现,明确系统的功能需求

  • 良好的系统结构:分解系统功能,形成良好的系统架构

  • 易于理解和沟通:使用图形化表示,便于团队成员和利益相关者理解和沟通

2.5.3 分析类的三种构造型

界面类(Boudary Class):

  • 定义:用于处理系统与外部世界的交互,如用户界面和外部系统接口

  • 职责:管理输入和输出,将外部信息转换为系统内部可处理的格式

  • 示例:登录界面、API接口

实体类(Entity Class):

  • 定义:表示系统中的业务对象和持久化数据

  • 职责:存储和管理业务数据,通常与数据库中的表对应

  • 示例:用户、订单、产品

控制类(Control Class):

  • 定义:负责实现用例的控制逻辑和业务规则

  • 职责:协调边界类和实体类之间的交互,实现具体的业务逻辑

  • 示例:订单处理器、支付处理器

2.5.4 评估用例

当评估一个特定的用例是否有效时,可以使用三个常见的测试来衡量其价值和合理性:Boss测试、EBP测试和Size测试

Boss测试:

  • 定义:Boss测试是指用例是否对企业的决策者(通常是老板或高级管理层)具有实际的价值和意义

  • 评估标准:用例需要能够解决或支持企业的关键问题、战略目标或优先事项。它通常与业务的长远发展或成本效益有关。如果一个用例能够通过Boss测试,意味着它在企业决策者眼中时有利的、有意义的

EBP测试:

  • 定义:Enterprise Business Processs测试评估一个用例是否与企业的业务流程和操作流程相一致

  • 评估标准:用例需要符合企业日常运营中的需求和标准流程。它应该时一个企业正常运作所必需或至少时有助于优化和改进业务流程的一部分。EBP测试确保用例能够在企业整体运营中无缝集成和执行

Size测试:

  • 定义:Size测试衡量一个用例的复杂度和规模是否适当

  • 评估标准:用例应该即不过于庞大复杂以至于难以实施和管理,也不应该太小以至于无法提供实际价值。适当的规模意味着用例能够在合理的时间内完成,并且对资源(如人力、技术、预算等)的需求是可控的

2.6 识别设计元素

识别设计元素是设计阶段的重要任务。它涉及识别和定义系统的主要组件及其相互关系,以确保系统能够实现所需的功能。主要设计元素包括子系统和接口。

2.6.1 子系统、接口

子系统(Subsytem):

  1. 定义:是一个较大的系统中的独立部分,它可以独立开发和运行,通常代表一个特定的功能区域或逻辑部分

  2. 职责:

    • 封装一组相关的类和组件

    • 提供特定的功能和服务

    • 通过定义明确的接口与其他子系统或外部系统进行交互

  3. UML表示:通常用一个带有内部组件的矩形表示,并标注为"Subsystem"

  4. 示例:一个电子商务系统的子系统可以包括用户管理子系统、订单处理子系统、支付子系统等

接口 :

  1. 定义:是一个抽象类型,定义了一组方法而不实现它们,它规定了实现类必须提供的行为

  2. 职责:

    • 定义系统中组件或类之间的交互七月

    • 促进模块间的松耦合

    • 提高系统的灵活性和可扩展性

  3. UML表示:带有关键字​的圆角矩形表示,也可以用小圆圈和依赖箭头表示实现关系

  4. 示例:在支付子系统中,可以有一个PaymentProcessor接口,定义处理支付的基本方法,如processPayment()

2.6.2 子系统与包的区别

子系统:

  • 功能划分:子系统表示系统的功能部分或逻辑模块

  • 自包含:子系统是自包含的,可以独立开发和运行

  • 接口交互:子系统之间通过定义明确的接口进行交互,强调模块间的功能协作

  • 抽象级别:子系统处理较高的抽象级别,关注系统的架构和功能划分

包:

  • 组织结构:包用于组织和管理模型中的元素,如类、用例、组件等

  • 分层结构:包帮助构件系统的分层机构,主要用于代码管理和命令空间的组织

  • 不强调独立性:包主要是逻辑上的分组,不强调独立开发和运行

  • 依赖关系:包之间可以有依赖关系,但不定义通过接口进行交互

2.7 识别运行时机制

识别运行时机制是设计过程中一个关键的步骤,旨在确定系统在运行时的行为和结构,特别是在并发执行和资源管理方面。这个过程设计对系统的并发需求进行分析,并识别和定义系统中的进程和线程

主要步骤:

  1. 分析并发需求:

    • 主要活动:

      • 确定并发需求:分析系统的功能需求,确定哪些操作需要并发执行。例如,用户交互、后台处理、实时数据处理等

      • 识别并发性来源:确定并发性的来源,如用户请求、外部系统交互、定时任务等

    • 输出:

      • 并发需求文档:记录系统的并发需求和并发性来源

      • 并发场景图:使用UML的活动图或顺序图表示并发场景

  2. 识别进程和线程

    • 主要活动:

      • 确定需要的进程:识别系统中需要独立执行的主要任务和功能模块,并将它们划分为不同的进程

      • 确定需要的线程:在每个进程中,识别需要并发执行的任务和操作,并将它们划分为不同的线程

    • 输出:

      • 进程和线程模型:使用UML的类图和组件图表示进程和线程及其关系

  3. 识别进程生命周期:

    • 主要活动:

      • 定义进程的创建和销毁:确定进程的创建、运行、暂停和终止的条件和机制

      • 管理线程的生命周期:确定线程的启动、执行、等待和终止的条件和机制

    • 输出:

      • 进程生命周期图:使用UML状态图表示进程的生命周期

      • 线程管理方案:记录线程的生命周期管理策略和机制

  4. 将设计元素映射到进程

    • 主要活动:

      • 映射类和对象到进程:将系统的设计元素分配到不同的进程中, 确保每个进程中的任务能够被有效管理和执行

      • 定义进程间的通信和协作:确定进程之间的通信方式和协作机制,如消息传递、共享内存、远程调用等

    • 输出:

      • 设计元素映射文档:记录设计元素到进程的映射关系

      • 进程通信图:使用UML的序列图或通信图表示进程间的通信和协作

2.7 识别分布

在分布式系统设计中,识别分布是一个关键步骤,旨在确定系统如何在多个物理或虚拟节点上进行部署和运行。UML提供了工具和图表来帮助建模分布式系统的结构和行为

2.7.1 分布模式

C/S模式:

  1. 三层模式:

    • 表示层:负责用户界面和用户交互

    • 业务逻辑层:处理业务规则和逻辑

    • 数据访问层:负责于数据库或其他数据存储进行交互

    • 示例:典型的Wen应用程序,浏览器(表示层)、Web服务器(业务逻辑层)和数据库服务器(数据访问层)

  2. 胖客户端模式:

    • 定义:客户端承担了更多的业务逻辑和处理任务,服务器主要提供数据访问和存储服务

    • 优点:减轻服务器负载,提高客户端的响应速度

    • 缺点:客户端的复杂性和资源需求增加

    • 示例:传统的桌面应用程序

  3. 瘦客户端模式:

    • 定义:客户端只负责用户界面和少量的逻辑处理,大部分业务逻辑和数据处理都在服务器端进行

    • 优点:客户端简单,易于维护和更新

    • 缺点:依赖服务器的性能和稳定性

    • 示例:Web浏览器访问的云端应用

P2P模式:是一种去中心化的分布模式,节点既可以作为客户端,也可以作为服务器,每个节点都可以直接与其他节点进行通信

  • 定义:所有节点在网络中地位平等,既可以提供服务,也可以请求服务

  • 优点:提高系统的容错性和扩展性,减少对中心服务器的依赖

  • 缺点:管理和协调复杂,安全和一致性挑战较大

  • 示例:文件共享网络(如BitTorrent)、分布式计算平台

2.7.2 主要步骤

步骤:

  1. 定义网络配置:

    • 主要活动:

      • 确定系统拓扑:定义系统中的节点、网络连接和通信路径

      • 确定网络协议和通信机制:确定节点之间的通信协议(HTTP、TCP/IP)和数据传输方式

    • 输出:

      • UML部署图:展示系统的物理节点、设备和它们之间的连接关系

      • 网络配置文档:记录网络拓扑、通信协议和配置细节

  2. 分配进程到节点

    • 主要活动:

      • 确定进程部署策略:根据系统的分布模式和需求,将不同的进程分配到适当的节点上

      • 优化资源利用:考虑节点的性能、资源和负载,优化进程分配以提高系统性能和可靠性

    • 输出:

      • 进程分配图:使用UML部署图展示进程到节点的映射关系

      • 分布策略文档:记录进程分配的策略、理由和具体配置

2.8 子系统设计

设计定义子系统的内部结构、接口实现及其子系统之间的依赖关系。使用UML可以清晰地描述这些设计元素,确保系统的模块化和可维护性

主要步骤:

  1. 构建接口实现:

    • 主要活动:

      • 定义接口:为每个子系统定义接口,明确它们提供的服务和方法。这些接口定义了子系统与外部的交互契约

      • 实现接口:为每个接口提供具体的实现

    • 输出:

      • 接口定义文档:记录每个子系统的接口及其方法

      • UML类图:展示接口及其实现类

  2. 分布子系统行为到子系统元素

    • 主要活动:

      • 分布子系统行为:将子系统的整体行为分解为更小的功能单元,并分配给子系统内的不同元素

      • 定义内部协作:确定子系统内部各元素之间的协作方式,确保它们能够共同完成子系统的职责

    • 输出:

      • UML序列图或活动图:展示子系统内部元素之间的交互和行为流程

      • 类图或组件图:展示子系统内的类或组件及其关系

  3. 构建子系统的依赖关系:

    • 主要活动:

      • 识别子系统之间的依赖:确定一个子系统是否依赖于另一个子系统提供的服务或数据

      • 定义依赖关系:使用UML图表明确表示子系统之间的依赖关系,以确保系统的整体架构清晰和稳定

    • 输出:

      • UML组件图:展示子系统及其之间的依赖关系

      • 依赖关系文档:记录子系统之间的依赖关系及其原因

2.8 类设计

主要步骤:

  1. 创建初始的射击类

    • 主要活动:

      • 识别类:从需求文档和用例中识别系统需要的类

      • 创建类:在UML类图中创建这些类,并初步定义他们的职责

    • 输出:

      • 初始设计类图:展示系统中的类及其基本结构

  2. 定义操作、方法

    • 操作和方法却别:

      • 操作:类的行为或功能,在类中声明但不具体实现,操作是接口的一部分

      • 方法:操作的具体实现,是在类中实际执行的代码

    • 主要活动:

      • 定义操作:为每个类定义操作,这些操作描述了类可以执行的功能

      • 实现方法:为每个操作提供具体的方法实现

    • 输出:

      • 类图:

      • 方法实现文档:记录每个操作的具体实现细节

  3. 定义状态:

    • 主要活动:

      • 识别类的状态:确定类在其生命周期中可能具有的不同状态

      • 定义状态妆化:描述类在不同状态之间的转换条件和触发事件

    • 输出:

      • 状态图

  4. 定义属性:

    • 主要活动:

      • 定义类的属性

      • 属性类型和可见性

    • 输出:

      • 类如

  5. 定义关系

    • 主要活动:

      • 识别类之间的关系

      • 定义关系类型

    • 输出:

      • 类图

2.9 数据库设计

主要步骤:

  1. 持久设计类到数据模型的转换

    • 主要活动:

      • 识别持久类:从UML类图中识别需要持久化到数据库的类

      • 定义映射关系:将每个持久类的属性映射到数据库表的字段

      • 选择数据类型:根据需求和数据库管理系统(如MySQL, PostgreSQL)选择合适的数据类型

    • 输出:

      • 数据模型:包括数据库表、字段和关系的物理设计

      • 映射文档:记录每个类到表的映射关系和数据类型选择

  2. 分布类的行为到数据库

    • 主要活动:

      • 识别需要持久化的操作:分析每个类的行为和与数据库相关的操作

      • 转换业务逻辑:将类的行为转换为数据库的查询语言或存储过程

      • 优化查询:以提高数据库性能和效率

    • 输出:

      • 存储过程或SQL查询:实现类的方法的数据库存储方式

      • 性能优化文档:记录优化查询的策略和方法

2.10 软开风险

在软件开发过程中,存在许多潜在的风险

常见的软件开发风险:

  • 需求风险:

    • 不明确的需求:需求不清晰

    • 需求变更:需求在开发过程中频繁变化

  • 技术风险:

    • 新技术的采用:使用未经过测试的新技术或工具

    • 技术不成熟:技术本身还不够成熟,存在不确定性

  • 项目管理风险:

    • 时间超支:项目未能按时完成

    • 成本超支:项目预算超支,成本控制不当

    • 资源不足:开发团队缺乏必要的人力或技能

  • 团队风险:

    • 团队协作问题:团队成员之间缺乏有效的沟通和合作

    • 人员流动:关键人员离职或调动

  • 质量风险:

    • 缺陷和错误:软件中存在大量的缺陷和错误

    • 不符合标准:软件质量不符合预期的标准或规范

  • 外部风险:

    • 法律和合规:项目不符合法律法规或行业标准

    • 市场变化:市场需求变化,导致项目目标发生变化

避免风险的办法:

  1. 需求管理:

    • 需求分析和澄清:在项目初期进行详细的需求分析,确保需求明确、具体

    • 需求变更控制:建立严格的需求变更管理流程,评估变更的影响并得到相关方的批准

  2. 技术管理

    • 技术评估:在采用新技术前进行技术可行性评估和小规模试点

    • 技术培训:为团队提供必要的技术培训,提升团队对新技术的掌握程度

  3. 项目管理:

    • 项目规划:制定详细的项目计划,包括时间表、里程碑和资源分配

    • 风险管理:定期进行风险识别和评估,制定风险应对策略

    • 进度跟踪:定期监控项目进展,及时发现并解决问题

  4. 团队管理:

    • 有效沟通

    • 团队建设

  5. 质量管理:

    • 测试和评审:在开发过程中进行持续的测试和代码评审,及时发现并修复缺陷

    • 质量标准:指定和遵循软件开发质量标准和规范,确保软件质量

  6. 外部风险管理:

    • 合规检查:确保项目遵循相关的法律法规和行业标准

    • 市场调研:定期进行市场调研,了解市场需求变化,及时调整项目目标和策略

2.11 四层元建模架构

four-layer metamodeling architecture 是一种用于定义复杂模型的精确语义的成熟基础设施

四层架构:

  • 元元模型(Meta-metamodel):用于定义元模型的语法和语义。元元模型描述了建模语言本省的结构和规则,是所有其他模型层次的基础。在UML中,元元模型通常指MOF(Meta Object Facility),它定义了如何创建和管理元模型

  • 元模型(Metamodel):在元元模型之下,用于定义特定建模语言的元素及其关系。例如,UML的元模型定义了用例图、类图、活动图等的元素和关系。元模型本质上是对模型的描述,用来定义模型中可以使用的各种构造块

  • 模型(Model):模型是在元模型的框架内创建的具体实例。模型使用元模型中的元素来表示系统的特定方面或视图,例如,一个UML类图模型会包含具体的类、接口和题目之间的关系。这一层次的模型用来描述实际系统或问题领域

  • 用户对象(User Object):用户对象是模型中的具体实例,代表实际系统中的特定对象或实体。例如,在一个UML类图模型中,用户对象可能是具体的类实例(如"订单"、"客户"等)。这些实例是开发和分析系统时的最终目标

作用:

  • 分离关注点:每一层专注于不同的抽象级别,减少了复杂性,使得每一层都可以独立于其他层次

  • 灵活性

  • 标准化

  • 复用性

2.12 领域分析

旨在深入理解和捕捉所要解决的业务领域的问题和需求。通过领域分析,可以确保开发的系统能够满足实际业务需求,并为后续的设计和实现提供坚实的基础

在进行领域分析时,类图主要用于表示业务对象。

3.设计原则与模式

3.1 GoF

GoF指的是《设计模式:可复用面向对象软件的基础》

这本书一共提出了23中常见的设计模式,主要分为三种类别:建造型(Creational Patterns)、结构型(Structual Patterns)、行为型(Behavioral Patterns)

  1. 建造型:建造型模式关注对象的实例化过程,帮助我们在创建对象的时候尽量降低耦合度,同时提高灵活性。常见的建造型模式包括工厂方法模式,抽象工厂模式、建造者模式、单例模式、原型模式

  2. 结构型:结构型处理类和对象之间的关系,通过组合类和对象来形成更大的结构。这些模式有助于确保系统的各个部分能够协同工作。一些常见的结构型模式包括适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式和代理模式

  3. 行为型模式:关注对象之间的通信和责任分配。它们有助于实现对象之间更灵活的交互,以及更好的代码组织。行为型模式包括模板方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模式、解释器模式、状态模式、策略模式和访问者模式。

作用:

  • 减少代码的耦合程度

  • 避免一些逻辑错误

  • 有利于代码复用

3.1.1 基本原则

设计模式中著名的SOLID原则概括了面向对象设计的五个基本法则,帮助开发者构建更健壮、灵活的系统。在设计代码架构时,开发者不应仅限于常见的设计模式,而应更深入理解并实践SOLID的核心思想

3.1.1.1 开闭原则(Open/Closed Principl, OCP)

软件实体(如类、模块、函数等)应对扩展开放,对修改关闭。这通常使用接口或抽象类实现,允许通过添加新的子类来扩展功能,而不需修改现有代码

3.1.1.2 里氏替换(Liskov Substitution Principle, LSP)

子类对象应能够替换它们的父类对象而不破坏程序的正确性。设计子类时,应保证能够替代父类功能,不引入额外异常行为或削弱原有的功能。

3.1.1.3 接口隔离(Interface Segregation Principle, ISP)

应将大接口(提供多功能的接口)拆分为更小、更具体的接口,使实现接口的类只需关心它们真正需要的方法。

3.1.1.4 依赖倒置(Dependency Inversion Principle, DIP)

高层模块不应依赖于地层模块,两者都应依赖于抽象,抽象不应依赖于细节,细节应依赖于抽象。

3.1.1.5 迪米特法则(Law of Demeter)

也称最少知识原则,如果两个实体不需要直接通信,就不应发生直接调用。

3.1.2 常见设计模式

3.1.2.1 建造型
工厂模式(Factory)

概述:提供了一种将对象的实例化过程封装起来的方式,使得客户端可以通过调用工厂类的方法来创建对象,而无需直接调用对象的构造函数。

通常会涉及以下角色:

  • Factory:负责创建对象的接口,通常是一个抽象类或接口。工厂类中通常包含一个或多个用于创建对象的方法。

  • ConcreteFactory:实现了工厂接口,负责创建具体的产品对象,

  • Product:定义工厂方法所创建的对象的接口,可以是一个抽象类或接口。产品通常包含对象的共同特性和行为。

  • ConcreteProduct:实现了产品接口,具体产品是工厂方法所创建的对象的实例

主要作用:

  • 封装对象的创建过程:Factory模式将对象的实例化过程封装在工厂类中,客户端可以通过调用工厂类的方法来创建对象,而无需知到对象的具体实现细节。

  • 隐藏对象的创建逻辑

  • 提高代码的可维护性和可扩展性

适用场景:

  • 当对象的创建过程比较复杂,或者需要根据不同的条件创建不同对象时,可以适用工厂模式将创建逻辑封装起来

  • 当需要在不同的地方创建相同类型的对象时,可以使用工厂模式来统一对象的创建过程。

抽象工厂(Abstract Factory)

概述:定义一个接口来创建几种不同种类的类,其中每个种类可能有若干相互依赖的组件。用户无需指定需要用到哪些特定的组件。

适用场景:

  • 当需要创建一组相关或依赖的对象时,会使用这种方式。

建造者(Builder)

概述:定义一个接口,允许用户指定对象的步骤和过程;核心是分离的构造和表示两个步骤。

适用场景:

  • 主要用于创建复杂的对象,或者希望用相同的创建过程可以创建不同的表示。

原型(Prototype)

概述:通过复制的方式创建对象,使用于构造表示比较复杂的对象。

单例(Singleton)

概述:确保一个类只能有一个实例,并提供一个全局访问点来获取这个实例

应用场景:

  • 线程池

通常涉及以下角色:

  • Singleton类:负责创建自己的唯一实例,并提供了一个静态方法(通常命名为getInstance()),该方法用于获取该实例。Singlton的构造函数通常被声明为私有的,以防止其他类直接实例化它

主要作用:

  • 确保唯一实例

  • 全局访问点

  • 延迟实例化:在第一次调用getInstance()方法才创建实例

3.1.2.2 结构型
适配器(Adapter)

概述:创建一个中间层,使得已有接口和新接口能交互。一般已有接口是不可变或不方便修改的,例如glibc库等。它允许将已有接口转换成客户端所期望的另一个接口,从而解决接口不兼容问题

通常涉及以下几个角色:

  • Target:客户端所期待的接口,也是客户端代码所调用的接口

  • Adaptee(被适配者):需要被适配的接口,它定义了现有系统中的功能

  • Adapter:将Adaptee的接口转换为Target接口的类,Adapter通过包装了一个Adaptee的实例,它实现了Target接口,并在其内部调用Adaptee方法

主要作用:

  • 兼容性:Adapter模式可以帮助解决由于接口不兼容而导致的系统组件无法协同工作的问题

  • 复用性:Adapter模式可以将现有的类和接口复用到新的环境中,而无需修改原有代码

  • 透明性:客户端可以完全不知道Adapter是如何将Adaptee的接口转换成Target接口的,从而保持了客户端的透明性

组合(Composite)

概述:允许你将对象组合成树形结构以表示“部分-整体”的层次结构。Composite模式使得客户端可以统一地处理单个对象和组合对象,从而简化客户端的代码。

通常涉及以下角色:

  • Component:定义了组合中所有对象的通用接口,可以是抽象类或接口。在Composite模式中,Component角色既可以表示单个对象(Leaf),也可以表示组合对象(Composite)

  • Leaf:是组合中的叶子节点对象,它没有子节点。Leaf对象实现了Component接口的所有方法,但通常不包含对其他对象的引用

  • Composite:是组合中的符合对象,它包含一个或多个子节点。Composite对象实现了Component接口的所有方法,并提供了管理子节点的方法,如添加、删除、获取子节点等。

主要作用:

  • 统一处理:Composite模式使得客户端可以统一地处理单个对象和组合对象,无需区分它们的具体类型,从而简化了客户端的代码

  • 递归结构:Composite模式通过递归结构来表示对象的层次结构,使得可以轻松地处理复杂的对象结构。

  • 灵活性:由于Leaf和Composite都实现了相同的接口,因此可以随时将Leaf替换为Composite或反之,从而使得系统更加灵活

适用场景:

  • 当需要表示对象的部分-整体层次结构,并且希望客户端能够统一地处理单个对象和组合对象时,可以使用Composite模式

  • 当需要对树形结构进行递归遍历,并且希望能够轻松地处理复杂的对象结构时,可以使用Composite 模式

桥接(Bridge)

概述:将抽象部分和实现部分通过组合的方式分离(组合替代继承),很多时候都会用到这个模式,例如拆分庞大功能的类

代理(Proxy)

概述:提供一个代理对象来控制对另一个对象的访问,从而可以在访问对象时引入额外的Indirection,以控制或者管理对对象的访问。

通常涉及以下角色:

  • Subject:定义了真实对象和代理对象的公共接口,这样代理对象能够在任何时候都能够代替真实对象

  • RealSubject:定义了代理所代表的真实对象,是代理模式中的实际执行者。

  • Proxy:保存一个引用使得代理可以访问实体,并提供一个与Subject的接口相同的接口,这样代理就可以用来代替实体

主要作用:

  • 远程代理:当对象位于不同的地址空间,通过代理来代表远程对象,可以隐藏远程对象的具体实现细节,同时提供本地化的访问

  • 虚拟代理:延迟创建代价高昂的对象,直到真正需要的时候才去创建,可以提高系统的性能

  • 保护代理:控制对对象的访问,例如限制对象的访问权限,只允许特定用户访问对象。

  • 缓存代理:为一些开销大的运算结果提供缓存,以便在后续请求中快速获取,提高系统的效率。

适用场景:

  • 当访问资源的开销较大,或需要权限检查等额外功能时,会使用这个模式

  • 当需要对对象的访问进行额外的安全检查、性能优化或者远程访问时,都可以考虑使用Proxy模式。

装饰器(Decorator)

概述:定义函数的接口与被覆盖函数的接口相同,用户可以无感调用扩展功能的接口。

适用场景:

  • 定义函数的接口与被覆盖函数的接口相同,用户可以无感调用扩展功能的接口

  • 适合在原接口上无感扩展新的功能

享元(Flywight)

概述:当有大量结构体共享一部分相同的数据时,将这部分数据独立出来,所有结构体共享这部分数据。适用于不可变状态较多时节省内存。

外观(Facade)

概述:提供了一个统一的接口,用于访问子系统中的一组接口,从而简化了子系统的使用和客户端与子系统之间的交互。

通常涉及以下角色:

  • Facade:提供了一个高层次的接口,用于统一访问子系统的一组接口。Facade将客户端的请求委托给适当的子系统对象进行处理,隐藏了子系统的复杂性,使得客户端和子系统之间的耦合度降低

  • Subsystem:实现了系统的功能,但可能存在于不同的类中。每个子系统都负责某一特定的功能或一组相关的功能。

主要作用:

  • 简化接口:Facade提供了一个简单的接口,隐藏了子系统的复杂性,使得客户端可以更容易地使用子系统。

  • 解耦客户端和子系统:Facade将客户端与子系统之间的依赖关系解耦,客户端只需要与外观对象进行交互,而不需要直接访问子系统的接口

  • 促进松耦合:Facade模式有助于促进系统的松耦合,使得子系统可以独立地进行修改和演化,而不会影响到客户端。

适用场景:

  • 当系统中存在复杂的子系统结构,需要将其隐藏起来以简化客户端的使用时

  • 当需要将系统的各个部分进行解耦,以提高系统的灵活性和可维护性时

  • 当需要提供一个统一的接口,隐藏系统的复杂性,并且对客户端代码进行封装时。

3.1.2.3 行为型
职责链(Chain of responsibility)

概述:让请求以链式的形式逐一被处理

适用场景:

  • 解耦发送者和执行者时常用

命令(Command)

概述:将操作抽象为对象(通过函数指针等项式),从而允许使用不同的请求、队列或日志来参数化其他对象。

适用场景:

  • 常用于参数化对象或者排队执行一些操作。

策略(Strategy)

概述:定义了一系列算法,并将每个算法封装到具有共同接口的独立的类中,使得它们可以相互替换。Strategy Pattern让算法的变化独立于使用算法的客户端

通常涉及以下角色:

  • Context:维护一个对Strategy接口的引用,用于执行算法。Context类通常包含一个设置Strategy的方法,以及一个执行Strategy的方法

  • Strategy:定义了一个算法的接口,所有具体Strategy类都实现了这个结构,通常包含一个执行算法的方法

  • ConcreteStrategy:实现了Strategy接口,提供了具体的算法实现

主要作用:

  • 分离算法:Strategy模式将算法的定义与使用分离开来,使得算法的变化独立于使用算法的客户端

  • 增加灵活性:由于算法可以相互替换,客户端可以在运行时动态地选择所需的算法

  • 提高复用性:Strategy pattern可以使得算法的实现可以被多个客户端共享和复用

适用的场景:

  • 当一个系统中存在多个算法,而且需要在运行时动态地选择所需的算法时,可以使用Strategy Pattern

  • 当需要在不同的情况下使用不同的算法,并且希望这些算法可以相互替换时

状态(State)

概述:将不同的状态设计为不同的类,并将对象的行为委托给当前状态所对应的类,这样,对象的状态发生改变时,只需要切换到相应的状态类,对象的行为就会随之改变。

通常涉及以下角色:

  • Context:定义客户端感兴趣的接口,维护一个对具体状态对象的引用,可以定义一个抽象的状态接口以供具体状态类实现

  • State:定义一个接口或抽象类,用于封装与Context相关的一个特定状态的行为

  • ConcreteState;实现State接口,提供状态的具体实现。

优点:

  • 通过State模式,可以将复杂的状态转移逻辑封装在不同的状态类中,使得Context类变得简单,并且易于理解和维护。State模式还具有狠好的可扩展性,可以方便地添加新的状态和相应的行为。

适用场景:

  • State模式在实际应用中常见于状态机、工作流程、订单生命周期等场景,例如在电商系统中,订单可以处于不同的状态(待支付、已支付、已发货等),每个状态对应着不同的行为,通过State模式可以将订单的状态逻辑封装在不同的状态类中,从而简化了订单管理的实现。

备忘录(Memento)

概述:将数据结构的状态保存一份,用于后续恢复状态

适用场景:

  • 常用于做snapshot等恢复状态的操作

模板(Template)

概述:在父类定义一个算法框架,子类实现算法的特定部分。

适用场景:

  • 常用于一些有固定执行逻辑的算法。

观察者(Observer)

概述:订阅监听模式,使用一个对象维护事件和对象间的一对多关系,当被监听事件产生时,会通知每个监听的对象,常用于需要处理事件,绑定回调函数的场景

通常涉及以下角色:

  • Subject(目标):被观察者。Subject维护了一个Observer list,可以动态地添加、删除Observer,当Subject的状态发生变化时,它会通知所有注册的Observer

  • Observer(观察者):Observer是订阅了Subject的对象,它们希望在Subject的状态发生变化时接收通知并进行相应的处理。通常,Observer对象会实现一个特定的接口,以便Subject可以调用通知方法

适用场景:

  • 事件处理

  • UI界面处理

  • 分布式系统中的消息订阅/发布

特点和应用方式:

  • 松耦合性:Subject和Object之间是松散耦合的,它们之间只通过抽象接口进行通信,不直接相互依赖

  • 多态性:Observer利用了多态性,使得Subject可以通知任何实现了Observer接口的对象。

  • 动态注册和解注册:Subject允许动态地添加、删除Observer,这使得系统更加灵活

  • 广泛应用于事件驱动编程:它使得对象能够对外部事件作出响应,例如用户交互、数据更新等。

访问者(Visitor)

概述:将算法与其作用的对象结构分离,通过在被访问的对象中添加一个接受方法来接受访问者,从而实现在不修改这些对象的类型的情况下定义新的操作。

适用场景:

  • 通常访问异构数据结构(例如树型)时常用

中介者(Mediator)

概述:引入一个中心对象来简化多个对象间的通信,从而减少这些对象之间的直接引用

适用场景:

  • 常用于解耦数据结构的相互引用

解释器(Interprete)

概述:定义了一种语法用于特定的问题,并通过一个解释器来解释语言中的句子,用于实现语言的语法或表达式的解析和执行。

适用场景:

  • 当特定问题有特定的写法时,常用interpreter来解决

3.2 GRSP

3.2.1 概述

General Responsibility Assignment of Software Patterns(一般责任分配软件模式) 是一组面向对象设计原则,旨在帮助软件开发人员更好地分配责任、设计清晰的系统架构,并提高系统的可维护性和可靠性

一些重要的原则:

  • 创建者(Creator):指导外面确定哪个类应该负责某个对象的实例。一般来说,具有最多信息并且与创建对象高度相关的类应该负责创建对象

  • 信息专家(Information Expert):指导我们将责任分配给那些拥有最多必要信息来执行该责任的类或对象,一个类应该承担它自己数据的操作,以及这些数据密切相关的操作

  • 低耦合(Low Coupling):指导我们减少各个模块之间的依赖关系,以降低系统的耦合度。这可以通过使用抽象、接口和依赖注入等方式来实现

  • 高内聚(High Cohesion):指导我们确保类的功能相关性强, 一个类内部的各个元素应该围绕一个目标或任务展开

  • 控制器(Controller):指导我们将系统的控制逻辑分配给一个专门的控制器类,以协调系统中的各个组件

  • 纯粹的虚构(Prue Fabrication):指导我们引入一个虚构的类,用于实现系统的功能,但该类并不对应任何现实世界的对象,也不依赖于现实世界中的对象

  • 间接(Indirection):指导我们引入一个间接层,以封装对某个对象或数据的直接访问,从而降低系统中各个组件之间的耦合

  • 保护性变化(Protected Variation):指导我们通过封装稳定的部分,暴露易于变化的接口和隔离变化影响,实现系统中各个组件之间的低耦合,提高系统的稳定性和灵活性

3.2.2 原则

3.2.2.1 创建者(Creator)

概述:用于确定哪个类应该负责创建某个对象的实例。该模式将对象的创建责任委托给了能够最好地决定对象创建方式的类。

Creator模式指导我们将对象创建的责任分配给一下类型的类

  • 具有最多信息的类:如果某个类拥有某个对象所需的所有信息,那么它就是最适合作为Creator的类。这是因为它具有创建对象所需的所有必要信息

  • 低耦合性的类:Creator类应该尽可能地与其他类保持低耦合性。这意味着它应该避免依赖于太多其他类

  • 高内聚的类:Creator类应该与其创建的对象具有高度相关性,这样可以确保Creator类的功能集中且易于理解。

举例:考虑一个图书管理系统,其中需要创建书籍对象。根据Creator模式,创建书籍对象的责任应该分配给一个能够提供书籍信息并创建书籍对象的类。比如BookFactory,BookFactory可以接收书籍的相关信息,然后使用这些信息创建相应的书籍对象。

3.2.2.2 信息专家(Information Expert)

概述:在给定的设计问题中,责任应该分配给那些拥有最多必要信息来执行该责任的类或对象。具体来说,Information Expert原则建议将责任分配给拥有所需信息的类或对象,因为它们具有最多的关于该信息的知识,可以最好地执行相应的任务,这有助于保持系统这个各个类的内聚性,并降低耦合度

举例:

考虑一个购物车系统,其中有一个功能是计算购物车中商品的总价格,根据Information Expert原则,这个责任最好分配给购物车类,因为购物车拥有关于商品的信息

3.2.2.3 低耦合(Low Coupling)

概述:尽量减少系统中各个模块之间的依赖关系,从而减低模块之间的耦合度。耦合度越低,系统的灵活性,可维护性和可扩展性就越高

实现方法:

  • 使用抽象和接口:通过定义抽象接口,将实现与接口分离,降低模块之间的直接依赖关系,提高系统的灵活性。模块之间通过接口进行通信,而不是直接依赖于具体的实现

  • 依赖注入:将模块所需的依赖项从外部传递给模块,降低模块之间的耦合度,这种方式使得模块更加独立,并且更容易进行单元测试和替换

  • 使用事件驱动架构:模块之间通过事件进行通信,而不是直接调用对方的方法,从而提高系统的灵活性和可维护性

  • 避免硬编码:避免在代码中硬编码依赖关系,而是将依赖关系配置在外部文件或者通过依赖注入的方式动态设置

3.2.2.4 高内聚(High Cohesion)

概述:指的是一个模块内部的各个元素彼此联系紧密,关注点的单一,功能相关性强。换句话说,就是一个模块内的元素应该围绕同一个目标或任务展开,彼此之间应该有紧密的联系和协作

优点:

  • 模块独立性强

  • 易于维护和理解

  • 提高了模块的复用性

  • 减少了错误和bug的出现

3.2.2.5 控制器(Controller)

概述:用于管理应用程序中的流程和交互逻辑。控制器负责接收来自用户界面或外部系统的输入,处理这些输入,并根据应用程序的逻辑和状态做出相应的响应。Controller通常是MVC(Model-View-Controller)架构模式中的一部分,它负责处理用户的请求并将它们传递给适当的模型进行处理,然后将结构传递给视图进行现实

主要责任:

  • 接收输入:Controller负责接收来自用户界面或外部系统的输入,例如用户的请求、命令或事件

  • 处理逻辑:一旦收到输入,Controller会根据应用程序的逻辑和状态进行相应的处理,可能会进行计算,调用其他模块或执行业务漏

  • 调度任务:Controller可能会调度一些任务或操作,例如更新数据库、发送请求到服务器等

  • 更新视图:在MVC架构中,Controller将模型的状态更新传递给视图,以便更新用户界面的显示

3.2.2.6 纯粹的虚构(Pure Fabrication)

概述:指的是在设计中创建一个独立的类(对象),该类的存在完全是为了实现系统的功能,而不直接对应于任何现实世界的对象。这个类是虚构的,它不代表任何实际的业务概念,也不依赖于其他领域对象。

目的:将系统中的功能逻辑集中在一个独立的组件中,而不是分散在多个业务对象中。通过这种方式,可以提高系统的模块化程度、降低耦合度,并且更容易进行功能扩展和维护。

举例:在一个图书管理系统中,可能存在一个pure fabrication叫做BookRepository,负责管理图书的存储和检索。这个类并不对应图书馆中任何实际部门或职责,它仅仅是为了一个管理图书而存在的抽象组件。通过图书管理的逻辑集中在BookRepository中,可以将与图书相关的功能解耦合,使系统更易于维护和扩展。

3.2.2.7 间接(Indirection)

概述:引入一个间接层,以封装对某个对象或数据的直接访问,这个间接层可以是一个接口,一个中介对象,或者其他形式的抽象,它将客户端代码与实际对象或数据解耦,提供了更灵活、更可扩展的设计

此外,中间层还可以提供额外的功能,比如对访问的控制、添加日志、实现缓存等

举例:

考虑一个图书管理系统,系统中有一个BookRepository类负责管理图书的存储和检索。如果直接在客户端代码使用BookRepositroy对象进行图书的增上改查操作,那么客户端代码与具体的存储实现(比如数据库)将会紧密耦合,不利于系统的维护和扩展。 这时候可以引入一个Indirection,比如BookService类,它封装了对BookRepository的访问,并提供了更高层次的接口供客户端使用。这样一来,如果需要更改存储实现,只需要修改BookRepository的具体实现,而客户端代码无需改变。

3.2.2.8 保护性变化(Protected Variation)

概述:旨在降低系统中各个组件之间的耦合度,使得系统的稳定性和灵活性更好地应对变化。该原则的核心思想是通过封装稳定的部分,并暴露易于变化的接口,从而保护系统中地的稳定性,使得变化不会轻易影响到系统的其他部分。

主要概念 :

  • 封装稳定的部分:将系统中不容易变化的部分进行封装,这些部分通常是稳定的核心功能或数据结构。通过封装这些部分,可以减少其他组件对其的直接依赖,从而降低了变化的风险

  • 暴露易于变化的接口:为系统中的组件提供一组稳定的接口,使得其他组件可以通过这些接口与稳定部分进行交互。这些接口应该设计得足够灵活,能够容纳未来的变化,同时尽量减少对内部实现的暴露

  • 隔离变化的影响:通过封装和抽象,使得系统中的变化局部化,变化只会影响到接口的实现,而不会影响到其他部分。这样可以减少变化对系统的影响范围,提高了系统的可维护性和可扩展性。

举例:考虑一个电子商务系统中,系统中的支付模块是一个稳定的核心功能,而支付方式可能会发生变化,为了保护系统中支付模块不受支付方式变化的影响,可以将支付模块进行封装,并定义一个稳定的支付接口。然后针对不同的支付方式,实现具体的支付接口实现类。这样一来,当支付方式发生变化时,只需要修改对应的支付接口实现类,而不会影响到系统中其他部分的正常运行。

应用了此原则的设计方法:

  • 数据驱动设计:将系统的行为与数据分离,使得行为可以通过修改数据来改变,而无需更改代码。这种方法有效地保护了系统免受变化的影响,因为数据的变化不会直接影响到系统的逻辑实现

  • 解释器驱动设计:通过使用解释器来处理特定的语言或命令集,这种设计允许通过修改解释的规则或脚本来改变系统行为,而无需修改底层代码

  • 迪米特法则和不要和陌生人说法原则:它们建议一个对象尽可能少地了解其他对象的内部细节,只与直接相关的对象交互。

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值