类图和对象图

Posted by fzy on January 26, 2024

第6章:类图和对象图

类图基本概念

类图是描述类、接口及其他们之间关系的图,显示了系统中各个类的静态结构,是一种静态模型。

类图的组成:2类元素,4种关系

image-20231207124810584

  1. 类(Class):
    • 解释: 类是对现实世界中具有相似属性和行为的对象进行抽象的概念。类包含了数据(属性)和行为(方法)
    • 例子: 如果考虑一个图书馆系统,”图书“就可以被建模成一个类,具有属性如书名、作者等,以及行为如借书、还书等。
  2. 接口(Interface):
    • 解释: 接口是一种抽象的数据类型,定义了一组方法的签名但没有具体的实现。类可以实现一个或多个接口,强制它们提供接口中定义的方法。
    • 例子: “支付接口”可以定义支付方法的签名,具体支付方式如支付宝、微信支付可以实现这个接口。
  3. 泛化(Generalization):
    • 解释: 泛化关系表示类之间的继承关系,其中一个类是另一个类的子类,继承了父类的属性和方法。实线+三角形箭头,指向父类
    • 例子: 如果有一个“动物”类,可以有子类如“哺乳动物”、”鸟类”,它们继承了”动物”类的一些共同特征。
  4. 关联(Association):
    • 解释: 关联表示类之间的连接关系,用于描述它们之间的关联性。关联可以是双向的,也可以是单向的。实线
    • 例子: 在图书馆系统中,“图书”类和”读者”类之间可能存在关联,表示读者与所借阅的图书之间的联系
  5. 依赖(Dependency):
    • 解释: 依赖关系表示一个类对另一个类的依赖,即一个类的变化可能会影响到另一个类。通常是通过方法参数或局部变量的方式实现的。虚线+箭头
    • 例子: 如果一个“图书馆”类的方法需要接收一个”图书”类的对象作为参数,那么“图书馆”类依赖于”图书”类
  6. 实现(Realization):
    • 解释: 实现关系表示类对接口或抽象类的实际实现。通常在接口和实现类之间建立实现关系。虚线+三角形箭头
    • 例子: 如果有一个“支付接口”,可以有类如“支付宝”、”微信支付”类来实现这个接口。

泛化和实现都是属于继承,三角形箭头,一实线一虚线

关联和依赖有些类似

类的符号:

image-20231207124908958

名称分栏必须出现,属性分栏和操作分栏可以出现或者不出现。但隐藏某个分栏并不代表分栏不存在。

类图与对象图的区别:

image-20231207125038843

  • 类图关注系统的静态结构,描述类、接口及它们之间的关系。
  • 对象图关注系统的动态结构,描述系统在某一时刻的对象实例及其之间的关系。

三个层次的观点

  • 概念层:描述应用域中的概念,与实现它们的类有关,但与现实方案与实现语言无关。
  • 说明层:描述软件的接口,而不是软件的实现。
  • 实现层:从实现的角度定义类和其实现
  1. 概念层(Conceptual Layer):
    • 解释: 在概念层,设计者关注的是问题概念和业务需求
    • 例子: 对于一个在线购物系统,概念层可能包括产品、用户、购物车等高层次的概念,而不关注具体的技术实现或界面设计。
  2. 说明层(Specification Layer):
    • 解释: 说明层建立在概念层的基础上,用于详细描述系统的功能和行为(demo),但仍然是独立于具体实现技术的。
    • 例子: 对于在线购物系统,说明层可能包括用户登录、浏览商品、添加到购物车等详细的功能描述(接口),但不涉及具体的编码或数据库设计。
  3. 实现层(Implementation Layer):
    • 解释: 实现层是最底层的设计,关注的是将说明层的规范转化为实际的可执行代码。在实现层,设计者考虑具体的编程语言、数据库设计、界面设计等技术实现细节。
    • 例子: 在实现层,设计者可能选择使用特定的编程语言(如Java、Python)、数据库(如MySQL、MongoDB)来实现说明层定义的功能。

类的组成部分

属性

UML属性语法:

可见性 名称【多重性】:类型 = 缺省值 {约束特性}

+------------------------------------+
|           Car                      |
+------------------------------------+
| - manufacturer: String = "Unknown" |
| # model: String                    |
| + year: int                        |
| * owners: List<String>             |
+------------------------------------+
一个 人员 类,包括属性 姓名、年龄、性别 和 电话号码
  • 可见性:Public(+)、Private(-)、Protected(#)

image-20231207125810495

  • 名称:属性的名称,是一个字符串

  • 多重性:低值—高值

    +------------------------+          +----------------------+
    |        Person          |          |       Address        |
    +------------------------+          +----------------------+
    | - name: String         |          | - street: String     |
    | * addresses: Address[] |          | - city: String       |
    +------------------------+          | - postalCode: String |
                                        +----------------------+
    Person 类有一个名为 addresses 的属性,它的多重性为 *,表示一个人可以拥有多个地址。
    Address 类没有显示多重性,但默认为 1,表示一个地址属于一个人。
    
  • 类型:定义属性的种类

  • 缺省值:属性的初始值

  • 约束特性:描述对属性的约束

操作

操作:描述类行为的函数,也被称为方法。

+------------------------------------------+
|      Calculator                          |
+------------------------------------------+
| - result: double                         |
+------------------------------------------+
| + add(a: double, b: double): double      |
| - subtract(a: double, b: double): double |
+------------------------------------------+

简单的计算器类,包括两个操作 add 和 subtract

操作的语法:

可见性 名称(参数表):返回类型表达式{约束特性}

  • 可见性:“+”:公有,”#“:受保护,”-“:私有
  • 名称:操作的名称
  • 参数表:语法与属性参数相同,个数任意
  • 返回类型表达式:依赖于语言的表述,可选
  • 约束特性:用来描述对操作的约束

两类操作:

  • 查询操作:执行顺序不重要
  • 修改操作:执行顺序很重要

类的关系

关联

关联表示类的对象之间的结构关系,在代码中表现为一个类以属性的形式包含对另一个类的对象的引用。

image-20231207130725376

表示方法:

  • 无向线段表示,表示双向关系
  • 有向线段表示:是一种单向关系

二元关联:两个类之间的关联

image-20231207130846747

角色

关联的两端的与类之间的接口表示该类在这个关联中的行为,称之为角色。每个关联有两端,所以每个关联有两个角色

将引出角色的类称为,将引入角色的类称为目标

角色的多元性:(多重性)

可以理解为ER图中一对多、多对多、多对一的关系

image-20231207131709895

image-20231207131817955

关联的名称

关联的名称表达了关联的内容,一般使用动宾结构短语。名称仅具有语意作用,不转换为代码。但是关联两端的角色会转换为代码

image-20231207131937435

company实例化为employer,person实例化为employee,0或1个雇主雇佣3个雇员

泛化

泛化关系(继承关系)定义类和包之间的一般元素和特殊元素之间的分类关系。

image-20231207132733128

如果一个类A(父类)的属性和操作能被另一个类B(子类)所继承,则类B不仅可以包含A的属性和操作,还可以添加自己独有的属性和操作,这就是泛化。

多态:

在泛化关系中,父类所定义的操作被子类继承后,可以表现出不同的行为。

多态允许在有继承关系的类中定义同名的操作,并在每一个类中有不同的实现。

image-20231207133800502

聚合和组合

聚合

聚合表示类和类之间的“整体——部分”关系,用空心菱形表示。聚合表示一个类拥有另一个类的对象。

image-20231207134028828

当整体类不存在时,部分类仍可能存在。部分类销毁的时候,整体类也将能够存在。

整体类和部分类均可独立存在

整体对象可以包含部分对象,但部分对象也可以独立存在。

+------------------------+          +----------------------+
|        Library         |          |       Book           |
+------------------------+          +----------------------+
| - name: String         |          | - title: String      |
| - location: String     |          | - author: String     |
+------------------------+          +----------------------+
| + contains: Book[]     |          | + partOf: Library    |
+------------------------+          +----------------------+

如果图书馆被关闭,书仍然可以存在,因为它们可以被移动到其他图书馆。(好聚好散)

组合

组合表示聚合的一种特殊情形,用实心菱形表示。一个部分类最多只能够属于一个整体类,当整体类不存在的时候,部分类将同时被销毁。

image-20231207134308473

部分类不可独立存在

整体对象的生命周期与部分对象的生命周期相同,部分对象不能独立存在。

+------------------------+          +----------------------+
|        House           |          |        Room          |
+------------------------+          +----------------------+
| - address: String      |          | - area: float        |
+------------------------+          +----------------------+
| + contains: Room[]     |          | + belongsTo: House   |
+------------------------+          +----------------------+

房间的生命周期与房子的生命周期相同,房间不能独立存在。(分崩离析)

聚合和组合的区别:

  • 聚合:整体端的重数可以大于1,部分类的重数是任意的
  • 组合:整体端的重数必须是1,部分类的重数是任意的

图书馆和图书,房子和房间

image-20231207134915826

关联和聚合的区别:

  • 关联:涉及的两个类是在同一个层次上的
  • 聚合:涉及的两个类处在不平等的层次上,一个表示整体,一个表示部分。

依赖

依赖表示一个类以某种形式依赖于其他类。当两个类处于依赖关系中时,其中一个类的改变可能会影响另一个类。比如说一个类将另一个类的对象作为自己的某个参数或者局部变量。

只要一个类用到了另一个类,但是和另一个类的关系不是太明显的时候,就可以把这种关系看成是依赖。

image-20231207141512072

person类的goToWork操作依赖moto类

约束规则

将约束条件放在括号{ }中,用自然语言或者其他常见的设计语言来描述。

image-20231207141728641

对象图

对象图是类图的实例,主要用于了解系统在某个特定时刻的具体情况,以发现类图中的错误,进而修正类图。

与类图的区别:

  • 对象只有名称和属性两个分栏,没有操作分栏
  • 对象的名称要加下划线
  • 对象的属性应该具有具体的值

image-20231207142208265

对象图的组成:

image-20231207142231126

image-20231207142802509

小结:

image-20231207143414112

建模步骤

image-20231207152058477

image-20231207152106151

  1. 先抓住主要分析类,然后根据需求文档找到所有的辅助类
  2. 确定那些是属性那些是类,如果有动词作用的就是类没有动作作用的只能作为属性
  3. 然后定义属性,根据常识和需求,在根据功能和状态,整体和局部
  4. 定义操作:从需求中寻找操作,从系统责任角度寻找,从状态转换中找,从流程中找
  5. 画出类图
  6. 画出类之间的关系

第7章:接口、抽象类和各种关联

抽象类

抽象类指的是那些不具有任何对象的类,其作用是为其他的类描述他们的公共属性和行为。

表示:

  • 斜体字表示抽象元素的名称
  • {abstract}约束来表示

image-20231207160327928

用abstract修饰的方法叫做抽象方法,由adstract修饰的类叫做抽象类

image-20231207160548359

接口

接口是一组没有实现的操作的集合。接口只提供操作的声明,不提供任何相应的功能代码。具体的功能代码由使用该接口的类实现,叫做实现关系。

类和接口不同,一个类可以有其形态的真实实例,但是一个接口必须至少有一个类来实现它。

表示:

image-20231207161503325

  • 接口中只包含普通函数,不包含构造函数
  • 接口中只提供方法的格式声明,而不能包含方法的实现
  • 接口中的所有函数都是公有的,不需要添加可见性

image-20231207162924154

image-20231207162935207

要实现接口,就必须在类名后包括接口,然后提供接口的每一个成员实现。

在接口成员的声明中不用写可见性,在类中相应接口成员实现定义中都用public。

接口的拓展

可以通过继承来对接口进行组合并拓展

image-20231207165645894

常量接口

接口一般用来表示一组行为,但也有时候用来表示静态数据,成为常量接口。

final static数据

标识接口

标识接口是指没有任何方法和属性的接口。

打个tag

抽象类和接口的相同与不同

相同:

  • 接口和抽象类都不能实例化
  • 都位于继承的顶端,用于被其他实现或继承
  • 都包含抽象方法,其子类都必须覆写这些抽象方法。

区别:

  • 抽象类中可以有自己的数据成员也可以有抽象的成员方法。接口中的方法只能有静态的不能被修改的数据成员,方法都是抽象的。
  • 抽象类表示的是一种继承关系,一个类只能使用一次继承关系,但是一个类却可以实现多个接口
  • 抽象类中的方法可以有默认行为,但接口中的方法不能有默认行为。

image-20231209160631110

  • 行为模型应该尽量选用接口
  • 需要定义子类的行为而且又要为子类提供通用的行为的时候采用抽象类

特殊的关联关系

限定关联

image-20231210132851931

更精确地描述关联的方式,引入了一个限定条件。这个条件通过一个额外的属性(限定符)来实现

+------------------------+                                  +----------------------+
|        Library         |                                  |         Book         |
+------------------------+                                  +----------------------+
| - name: String         |                                  | - title: String      |
+------------------------+             +--------------------| + partOf: Library    |
| + contains: Book[]     |------------ | - location: String |                      |
+------------------------+             +--------------------+----------------------+

contains 关联有一个限定符 location,它表示每本书在图书馆中的存放位置。

关联类

image-20231210133047571

连接两个类的关联关系中的附加类,它具有自己的属性和操作。关联类允许为关联添加更多的信息,而不必引入新的类。

+------------------------+             +----------------------+
|        Library         |             |         Book         |
+------------------------+             +----------------------+
| - name: String         |             | - title: String      |
+------------------------+             +----------------------+
| + contains: Borrowing[]|- ---------->| + partOf: Library    |
+------------------------+       |     +----------------------+
                                |
                                | 
                   +------------------------+ 
                   |         Borrowing      |            
                   |------------------------|            
                   | - startDate: Date      |            
                   | - dueDate: Date        |           
                   | + borrowedBook: Book   | 
                   | - returnDate: Date     |
                   +------------------------+      

Borrowing 是一个关联类,它记录了借阅书籍的相关信息

递归关联

image-20231210133119607

雇员既有manager又有普通employee

第8章:交互图

交互图简介

交互图描述对象之间的动态合作关系以及合作过程中的行为次序。通常用来描述一个用例的行为,显示该用例中所涉及的对象及其之间的消息传递情况。

交互模型建模:

  • 序列图:主要描述对象之间信息交换时的时间顺序
  • 协作图:用来描述系统对象间如何协作共同完成系统功能的要求

序列图展示了系统中对象之间的时间顺序交互,强调消息的发送和接收顺序。图中垂直的虚线表示对象的生命周期,而水平的箭头表示消息的流向

协作图强调对象之间的协作和通信,通过展示对象之间的连接关系和消息传递来描述系统的静态结构和动态行为

顺序图

顺序图强调的是消息发送的时间的先后顺序。在考察系统对象的交互的时候,从顺序图开始,然后将顺序图转换为协同图,分析系统在结构方面应该具备的特点。

顺序图组成部分:

  • 对象:用对象框(短式)表示,对象名要带下划线,消亡的时候在生存线上用一个❌表示。
  • 生存线:对象框下面画的一条垂直虚线
  • 激活期:对象生存线上的一个细长方形框,表示该对象的激活时间段
  • 消息:对象之间消息的发送和接受用两个对象生存线之间的消息箭头线表示。

image-20231210134418201

越靠近上面的消息越先发送。

消息的四种控制流

image-20231210135242444

  • 消息可以有名字,写在消息的箭头的直线上。
  • 消息有顺序,所以有顺序号。顺序号在消息名字的前面作为前缀,用冒号分割。顺序号分为两种:
    • 单调顺序号:严格按照消息的发送顺序排序
    • 过程顺序号:过程顺序号是嵌入式的。当一个消息启动了另一个消息序列的时候,消息序列内的各消息可以重新开始编号

简单消息:发送者发出消息后,控制流将等待接收者处理完消息并返回。

  • A 向 B 发送了一个简单消息,然后等待 B 处理完这个消息。

同步消息:同步消息中,控制流将一直等待,直到接收到消息的对象完成相应的操作

  • A 向 B 发送了一个同步消息,A 将一直等待,直到 B 处理完这个消息。

异步消息:发送消息的对象不需要等待接收消息的对象的响应,而是继续执行其他操作。

  • A 向 B 发送了一个异步消息,A 不会等待 B 处理完这个消息,而是继续执行其他操作。

返回消息:当一个对象调用另一个对象的方法并等待结果时,返回消息用于表示方法执行完成后的返回值

  • A 调用了 B 的一个方法,然后等待 B 处理完并返回结果

控制焦点(激活期)

在UML中,由消息引发的动作的执行过程被描述为控制焦点或者激活期

控制焦点的嵌套

  • 另一个控制焦点向右叠放在父控制焦点上
  • 子控制焦点中消息发送的顺序号可以用过程顺序号表示

建立顺序图

image-20231210141431605

image-20231210145110407

  1. 分析用例图
  2. 识别用例中的对象(接口、子系统、角色)
  3. 主动or被动对象
  4. 主动对象开始,主动对象结束
  5. 设置生命线
  6. 初始消息开始,画出交互信息
  7. 同步or异步
  8. 返回消息
  9. 控制焦点
  10. 增加时间约束和条件

协作图

协作图是交互图的另一种表现形式,在语义上和顺序图是等价的。协作图描述对象之间的连接关系,侧重说明哪些对象之间有消息传递。协作图中对象用对象图符表示,箭头表示消息发送的方向,编号表明消息的执行顺序。

协作图的构成

  • 对象
  • 连接:对象之间的语义联系,用对象之间相连的直线表示
  • 在连接上面传递的消息:用带箭头的直线表示

连接的通路

  • Field:对象能被另一个对象看见,是由于此对象是另一个对象的一部分,属性或成员变量
  • Paremeter:对象能被另一个对象看见,是因为此对象是另一个对象的某个操作的输入参数
  • Local:此对象能被另一个对象看见,是因为此对象生存在另一个对象的局部作用域中。
  • Global:此对象能被另一个对象看见,是因为此对象存在于全局作用域中。

image-20231210143512487

顺序图中常用的操作图

  • opt:可选操作符,监护条件为真执行操作符的主体,监护条件是方括号括起来的布尔表达式。

image-20231210144454189

  • alt:操作符的主体倍分割成几个分区,每个分区有一个监护条件,那个为真就执行哪一个,但只能一次执行一个。所有条件都为假就执行一个特殊分区。

    switch

image-20231210144650045

  • loop:循环执行,满足监护条件就循环执行

    for

image-20231210144715576

  • ref:引用,引用其他交互,比如子活动
  • break:执行循环中断后要执行的内容。

image-20231210144930204

  • par:并行执行,每一个分区表示一个并行计算,不同的分区有不同的生命线。

image-20231210145021117

alt(Alternative):switch

  • 符号: 使用 alt 关键字,后跟条件表达式。
  • 作用: 表示条件分支,表示在满足特定条件时,执行不同的消息序列。
alt (condition)
 // Sequence of messages for the true branch
else
 // Sequence of messages for the false branch

opt(Optional):if

  • 符号: 使用 opt 关键字,后跟条件表达式。
  • 作用: 表示可选的操作,仅在满足条件时执行。
opt (condition)
 // Optional sequence of messages

loopfor

  • 符号: 使用 loop 关键字,后跟条件表达式。
  • 作用: 表示一个循环结构,直到条件不满足为止。
loop (condition)
 // Loop body: sequence of messages

ref(Reference):

  • 符号: 使用 ref 关键字,后跟参与者的名称。
  • 作用: 表示引用其他参与者的消息序列
ref ParticipantName
 // Referenced participant's sequence of messages

par(Parallel):

  • 符号: 使用 par 关键字,后跟并行的消息序列
  • 作用: 表示并行执行的操作,用于描述同时发生的交互。
par
 // Sequence of messages in parallel

break

  • 符号: 使用 break 关键字。
  • 作用: 表示中断或跳出当前的控制流结构,类似于编程语言中的 break 语句。
break

通信图

通信图其实就是以前版本的协作图。通信图从空间角度反映对象之间的组织关系。通信图更加着重描述对象在交互中承担的角色,一个对象能扮演多个角色。

image-20231210145332301

  • 主动对象表示为双重边,用左右边为双线的矩形来表示。
  • “主动对象”变成了“与主动对象绑定的角色”,“被动对象”变成“与被动对象绑定的角色”。
  • 名称下面没有下划线
  • “临时链”变成“与临时链绑定的连接器”,“链”也和连接器绑定
  • 连接器是结构化类元中的或者协作中的两个结构化部件之间的连接。

看了半天,我感觉协作图就是通信图,没啥区别,只是表示的符号可能有一定不同。

顺序图和通信图的区别

image-20231210150403861

image-20231210150310234

第9章:状态图

状态机

事件驱动的动态行为:根据当前事件,以及对以前事件的响应的结果决定对当前事件的响应的软件对象的动态行为。

适合描述这种动态行为的建模手段就是状态机

  • 状态:记录以前的动态行为的结果
  • 变迁:描述软件对象对外来事件的响应以及响应的状态的变化。

与交互图的区别

  • 交互图强调的是对象之间的相互协作
  • 状态机强调对象本身对对象外部发生的事件的响应及伴随的状态的变化。

对于状态机,其描述的对象是广义的,只要对象的动态行为具有事件驱动的特性,就适合用状态机来建模

表示方法:

  • 状态圆角矩形表示:

image-20231211123438728

  • 两种特殊的状态:初始状态和终止状态
    • 用带实心圆的圆环表示的状态称为状态机的终止状态。
  • 变迁:两个状态之间的关系,表明在指定的时间发生后,在特定的条件下,对象执行指定的动作,并进入另一个状态。
    • 标识为连接两个状态的箭头,从前状态只想变迁后的状态。
  • 激发:对象发生了沿变迁箭头方向的变化,那么称变迁被激发
  • 触发事件:和变迁的激发联系在一起的事件

变迁的构成

  • 起始状态目标状态:都可以不止一个,表示汇合成一个控制流或者分解成多个控制流。
  • 触发事件:引发对象动作的事件
  • 触发条件:布尔表达式
  • 变迁动作:随着变迁的发生被激发的一个元计算

在表示的时候,触发事件、触发条件和变迁动作被表示成一个字符串放在表示变迁的箭头上。叫做变迁的文字标记

格式:触发事件 [触发条件] /变迁动作

状态、事件、条件、动作

  1. 状态: 开、关
  2. 事件: 按下开关按钮
  3. 转移条件: 如果灯是开的,按下按钮则转移到关的状态;如果灯是关的,按下按钮则转移到开的状态
  4. 动作: 在状态转变的同时,可能需要执行的动作是灯泡的亮灭
开----按下按钮 [灯是开的] /熄灯 ----> 关
关----按下按钮 [灯是关的] /亮灯 ----> 开

状态到状态,事件产生动作

状态图

状态图描述了一个对象或交互过程在其生命周期中对一系列外界激励所呈现出的不同状态及其相应的响应和活动。

image-20231211125829222

状态图的基本组成

状态图符、迁移图符、起始状态、终止状态、条件判定、发出信号、接受信号和并发等等。

image-20231211130435036

image-20231211131420346

状态的定义

状态表示的是一个对象或交互过程中的一个特定阶段

一个完整的状态包括:

  • 状态:省略的话就是匿名状态
  • 状态变量:状态图所描述的类的属性,可以是临时变量
  • 活动:该状态要执行的事件和动作
    • entry事件:指明在进入该状态时的特定动作
    • exit事件:指明退出该状态的特定动作
    • do事件:指明在该状态中要执行动作

image-20231211132159620

内部变迁不引起状态变化的变迁,不会触发entry和exit事件

延迟事件:某些事件不能被马上处理,但也不能忽略,必须在下一个状态处理。当一个内部变迁的触发事件时延迟事件的时候,在此变迁的动作的部分用保留动作defer代替。

延迟事件指定了一个时间期限,只有在经过一定的延迟时间后,事件才会被处理,然后状态机会根据该事件执行相应的状态转移。

状态的分类和属性

对象的状态属性分为:嵌套状态、顺序状态、历史状态、同步状态、并发状态

1. 嵌套状态(Nested State):

概念: 嵌套状态是指一个状态内部包含了另一个完整的状态机

通俗解释: 就像是一个小型的状态机嵌套在大型状态机内部,它有自己的状态和转移规则,可以在外部状态的某个情境下被激活

  1. 顺序状态(Sequential State):

概念: 顺序状态是指一个状态内部包含了多个顺序排列的子状态,只有一个子状态处于活动状态。

通俗解释: 在一个大状态内,有多个小状态按照顺序排列,每个时刻只有一个小状态是活动的,这样依次执行。

  1. 历史状态(History State):

概念: 历史状态用于表示在重新进入一个状态时,系统应该恢复到该状态的历史子状态。

通俗解释: 如果系统在离开某个状态时处于该状态的某个子状态,再次进入该状态时,可以选择恢复到上次离开时的子状态。

  1. 同步状态(Synchronized State):

概念: 同步状态表示多个子状态同时处于活动状态,并且它们具有相同的生命周期。

通俗解释: 多个子状态同时存在,它们的状态变迁是同步进行的,彼此保持一致。

  1. 并发状态(Concurrent State):

概念: 并发状态表示多个子状态可以同时处于活动状态,它们是彼此独立的,状态变迁互不影响。

通俗解释: 多个子状态可以独立运行,它们之间的状态变迁是并行执行的,不相互干扰

子状态

包含在某一个状态内部的状态

包含子状态的状态称为复合状态,不包含的就是简单状态。

image-20231211132944231

串行子状态:一个复合状态的子状态机所在的对象在其生存期内的任一时刻只能处于一个子状态。

image-20231211133609320

动作和活动

简单状态对应一个动作,组合活动中每个被嵌套的状态图对应着组合状态内正在进行的一个活动。

动作是原子级别的,活动是动作的集合

活动: 处理用户选择
	动作: 显示商品列表	
	动作: 接收用户选择
	动作: 检查货币输入
  • 动作:一组可执行的语句,有迁移性、原子性和连续性
  • 活动:一组可执行的动作,具有有限性和非原子性
状态的并发和同步

一个状态可以有多个并发的子状态复合前一由条件判断、并发分叉和并发连接图符来表示。

并发状态之间需要通信,或者具有一定的时序关系,称为并发中的同步。

同步是并发中的一种

image-20231211133808395

历史状态

历史状态是一个特殊的子状态,其记录了复合状态被转出时的活跃子状态。

在绘制的时候,用一个被圆环包围的字母H表示历史状态

  • 浅层历史状态:只记忆被转出变迁打断时最外层的活跃状态
  • 深层历史状态:记忆最深层的内嵌活跃子状态,用一个被圆环包围的带星号的字母H表示(H*)

历史状态指示器时一个伪状态,可以有几个进入他的状态迁移,但是没有离开它的状态迁移。

image-20231211141741960

状态迁移

状态迁移触发表示当一个特定的事件发生或某些条件满足的时候,一个源状态下的对象将完成一些特定的动作,称为迁移触发。

描述状态迁移的形式化语法格式:

  • 事件[条件]/动作表达式。发送子句
    • 事件:易发生并可能引发某种活动的一件事
    • [条件]:由方括号围起来的关系或者逻辑表达式
    • 动作表达式:一个触发状态迁移时可执行的过程表达式
    • 发送子句:动作的一个特例,说明调用的事件名(操作)是那个对象的。
转移的类型
  • 自转移:源状态和目标状态为同一个状态

    考虑一个红绿灯的状态机,当红灯持续亮起时,可能存在一个自转移,表示红灯状态一直持续,没有切换到其他颜色。

image-20231211142256682

  • 自动转移:根据情况,自动触发进入目标状态,在转移上没有事件

    在自动售货机的状态机中,当用户完成购买并投入足够的硬币时,系统可能自动将状态从“待售”切换到“已售”

image-20231211142404860

  • 条件转移:通过分支判断所确定的转移

    在咖啡机状态机中,当咖啡机处于“煮咖啡”状态时,如果水箱为空,可能存在一个条件转移,表示只有在水箱有水的情况下才能切换到“等待”状态。

image-20231211142431417

事件的种类

  • 状态内部事件:entry,exit,do和自定义事件

  • 消息:信号事件和调用事件

  • 时间事件:after事件、defer事件、when事件

    • after事件:以关键字after(时间表达式)说明,/后面跟有动作,例如:after(5min)/stop

      在交通灯控制系统中,绿灯状态 after 一定时间后可能触发黄灯状态。

    • defer:事件名/defer,延迟事件在本状态中不处理,推迟到下一个状态处理。

      在订单处理系统中,订单创建后可能存在一个 defer 事件,表示在一段时间后开始处理订单。

    • when事件,比如:when(温度>140) / 暂停

      在温室控制系统中,温度 when 达到一定值时可能触发通风状态。

建模步骤

  • 确定要进行系统控制的对象,可以从顺序图中寻找
  • 确定对象的起始状态和结束状态
  • 在对象的生命周期中寻找有意义的控制状态
  • 寻找状态之间的转换
  • 补充引起转换的条件
  • 绘制状态图并补充必要的文档说明

第10章:活动图

什么是活动图

状态图刻画的都是一些反映型的对象,也就是说对象的动作的执行是由对象外部发生的事件触发的。

但是有的兑现的动态行为并不是由事件驱动的,这类对象就是非反映型对象。当非反映型对象的动态行为被执行的时候,动态行为的一系列动作按照特定的控制逻辑(算法)顺序执行。

活动图是一种特殊形式的状态机,用于对计算流程和工作流程建模

  • 活动图的状态表示计算过程中所处的各种状态,而不是普通对象的状态。

用来为非反映型对象建模的状态机被称为活动图

和交互图的比较

  • 活动图更看重活动的控制流,描述在对象之间传递的操作
  • 交互图着重表现对象到对象的控制流,描述在对象之间传递的消息

和程序流程图的比较

  • 流程图描述的是处理的过程,有顺序、分支、循环等结构,有严格的顺序和时间关系
  • 活动图描述的是对象活动的顺序关系所遵循的规则,着重表现系统行为,而不是处理过程。通常也没有循环控制结构

和状态图的区别

  • 状态图强调在外部事件的驱动下,软件对象的控制在不同的状态之间的流动
  • 活动图强调在完成变迁引导下,对象的控制在活动之间的流动。状态迁移不需要触发,执行完自动进入下一个活动状态。

活动图类似于状态机的自动转移,不需要事件,只需要条件和变迁动作

image-20231211155952272

活动图的组成

活动图就是一个为非反应型对象的动态行为建模的活动状态机,主要包含三个方面的内容:动作状态,活动状态和无触发变迁

动作状态

动作时状态机内原子的计算的执行

  • 在活动图中,一个动作状态可以代表一次数据库查询、一次计算等操作。

原子性:

  • 动态行为的最小单位
  • 不可打断
  • 执行时间可以忽略

上下为平行直边两侧用圆弧连接的图形框来表示一个动作

image-20231211160633434

活动状态

活动是软件对象非原子的计算的执行,可以被分解成一系列动作

  • 在活动图中,一个活动状态可以代表一个业务流程、一个任务的执行过程等。

在大多数情况下,系统的动态行为可以用一系列的子过程来表达,而不需要细化到每一个原子的计算。

无触发变迁

无触发变迁又叫完成变迁,表示的是不包含触发事件的变迁。

  • 如果起始状态是一个简单状态,那么变迁在起始状态的入口动作和状态活动执行完毕之后被触发
  • 如果起始状态是复合状态,那么变迁在复合状态的内嵌状态机都大道结束状态后被激发

要注意的是,源状态的出口动作在变迁激发后执行,然后状态机转入变迁的目标状态。

在活动图中,一个无触发变迁可以表示状态之间的自动转换,例如在一个状态停留一段时间后自动切换到另一个状态。

分支

表示的是一个触发事件在不同的触发条件下激发的多个变迁。

用一个菱形表示,其包括:

  • 至少 一个输入变迁
  • 多个输出变迁(输出变迁都是带触发条件的完成变迁)

image-20231211162826424

循环

循环的结束条件用一个分支来表示,下图的分支带有两个转入变迁

image-20231211162939433

带有两个或者多个转入变迁的菱形符号称为合并

分解和汇合

在状态机图中,并发的控制流用并发子状态来建模,在活动图中,并发用分解和汇合来建模。

  • 分解:一个控制流被分解为两个或多个并发执行的控制流
  • 汇合:两个或多个控制流的同步
    • 只有当所有的控制流都到达汇合点之后,控制才继续向下流动
同步条

同步条是一个的水平线。

点那个同步条表示分解的时候,可以有一个转入变迁,两个或多个转出变迁。

当同步条用来表示汇合时,可以有两个或多个转入变迁,一个转出变迁。其中的转入变迁代表同步之前的多个并发控制流。

image-20231211222407818

泳道

语义上的相互关联活动状态的子集的划分是用泳道来实现的。

  • 泳道是活动图里对其中的活动按照其职责上的关联进行的划分。泳道在活动图中是一系列的垂直的隔断。
  • 每个活动都属于且只属于一个泳道
  • 泳道之间可以有变迁的传递
  • 泳道可以有名字

image-20231211222832262

对象流

对象流用虚箭头表示。用对象流表示对象不同活动之间的流动

  • 活动 1:学生借书
  • 学生从图书馆选择一本书。
  • 学生向图书馆提交借书请求。
  • 活动 2:图书馆管理员处理借书请求
  • 图书馆管理员接收学生的借书请求。
  • 图书馆管理员检查库存,确认书籍可借。
  • 图书馆管理员创建借书记录。

在这个例子中,对象流可以用来表示图书馆中的书籍对象是如何在学生和管理员之间流动的:

  • 当学生选择一本书时,可以通过对象流表示一个书籍对象从图书馆库存流向学生。
  • 当学生提交借书请求时,可以通过对象流表示一个借书请求对象流向图书馆管理员。
  • 当管理员确认书籍可借并创建借书记录时,可以通过对象流表示一个借书记录对象流向图书馆
  • 活动可以输入对象也可以输出对象。

image-20231211223257249

活动分解

可以用子图展示工作流的细节,然后将子图放在单独的图上,然后将活动状态指向描述细节的子图。

类似于预览图和详细图

image-20231211223538411

活动图的作用

活动图主要描述控制在活动之间的流动,是一种流程图,所以其主要有两种用途

  • 业务流程建模
    • 泳道表示不同的业务部门,用活动表示不同的业务步骤
    • 根据泳道的划分,确立相应的协同
    • 利用交互和交互图对软件的动态行为
  • 为对象的特定操作建模
    • 对操作的动态行为进行说明、可视化、建档、建造。
    • 活动图可以看作交互图的细化,用交互图定义对象之间的配合,活动图定义这些配合的实现。

活动图建模的步骤

image-20231211225504355

image-20231211225558009

第11章: 组件图

之前讲的类、对象、接口、类图、交互图、用例图、状态图、活动图等描述的都是概念空间之间的事物,适用于逻辑视图

但是我们必须将概念空间中的软件事物转换为对应物理空间的真实存在,这些真实存在就是用组件来表示的。组件图也用来构建实现视图

组件的特性

  • 存在于物理世界中:形式:计算机文件
  • 实现给定的动态行为
  • 建造时刻:源代码文件:是设计概念的实现
  • 运行时刻:可执行文件、运行库:实现给定的动态行为,可替代。

组件

组件是一个物理的和可替代的组成部分,该组成部分遵循并实现了一组给定的接口。组件属于实现视图

图形表示

image-20231212111053845

组件和类的区别与联系

区别:

  • 组件存在于物理空间
  • 类存在于概念空间

联系:

  • 组件和类都是分类符
  • 组件用来实现类的动态行为

组织形式和分类

和java类比,package来组织不同的类

组织形式:

  • 来组织组件
  • 用组件之间的交互关系来组织

分类

  • 源代码组件
  • 二进制组件
  • 可执行组件

组件和接口

组件化可以替换,让边界更加清晰,便于维护和升级。组件化的系统可以分布式

组件和接口之间的联系:

  • 实现关系:一个组件实现了一个接口,输出接口。被一个组件实现的接口是该组件的实现接口
  • 依赖关系:一个组件使用了另一个组件实现的接口所提供的服务。是输入接口

image-20231212112327403

组件的变体

标准变体:

  • 可执行文件
  • 库文件
  • 数据表
  • 文件
  • 文档

Rose中的组件变体

  • 组件

image-20231212113441921

  • 程序规范:一组子程序集合名

image-20231212113451690

  • 子程序体

image-20231212113519314

  • 主程序

image-20231212113539956

  • 包规范:类的头文件,包含类中函数的原型信息

image-20231212113555256

  • 包体:包含类操作代码(.cpp)

image-20231212113605654

  • 任务规范:具有独立控制线程的包

image-20231212113659424

  • 任务体:

image-20231212113716576

  • 数据库

image-20231212113751231

  • 虚包

image-20231212113805241

  • 虚子程序

image-20231212113826072

组件图的作用

按照建模的对象,为

  • 可执行文件和库文件(exe)
  • 数据表、文件、文档(data)
  • 程序api和源代码(src)
  • 为可执行文件和库文件建模

image-20231212114301832

  • 为数据表、文件和文档建模

image-20231212114626921

  • 为软件系统建模

    • 为程序API建模

    image-20231212115305353

    • 为源代码建模

    image-20231212115316328

UML2.0 的组件图

image-20231212115444111

  • 为组件的提供接口和要求接口建模

image-20231212115638210

另一种方式:

image-20231212115752402

组件内部结构的展示:

image-20231212115822290

image-20231212120202167

第12章: 部署图

之前讲了什么类图、用例图、状态图等等都是逻辑视图的内容,然后组件图讲的是物理实现,用在实现视图,然后这些物理资源需要部署,就需要用部署图来建模,部署图用于部署视图。

节点:节点表示一个运行时刻的物理对象,代表一类计算资源

部署视图:用来描述软件产品在计算机硬件系统和网络上的安装、分发和分布

部署视图的静态特性就用部署图来描述。包含了:

  • 节点
  • 节点和组件之间的联系
  • 节点和节点之间的联系

部署图的作用

一个UML部署图描述了一个运行时的硬件结点,以及在这些节点上运行的软件组件的静态视图。

部署图显示了系统的硬件,安装在硬件上的软件以及用于连接异构的机器之间的中间件。

创建一个部署模型能够:

  • 探究系统投产的相关问题
  • 探究你的系统和生产环境中其他系统的依赖关系
  • 描述一个商业应用主要的部署结构
  • 设计一个嵌入系统的硬件和软件结构
  • 描述一个组织的硬件/网络基础结构

投产、依赖、部署、嵌入系统、基础结构

部署图的组成

节点

节点是一个运行时刻的物理对象,代表一类计算资源,至少具备存储功能,并在大多数情况下具备数据处理的能力

节点的表示

用一个立方体来表示

image-20231212145132165

分为:

  • 处理器:具备计算功能
  • 设备:不具备计算功能

image-20231212145204687

还可以用扩充机制来描述

  • characteristics(特性)
  • processes(进程)
  • scheduling(调度)

image-20231212150134681

节点和组件

共性:

  • 都是分类符:都可以有实力,可以为其指定属性和操作
  • 都可以通过关系相互连接
  • 都可以参与交互

区别:

  • 组件用来参与系统的执行,节点执行组件的动态行为
  • 组件是逻辑概念的物理包装,节点是组件存在的物理载体

image-20231212150401149

节点之间的连接

节点之间最常见的关系是关联关系。

节点之间的关联关系代表节点之间的物理连接

  • 网络连接
  • 串口连接
  • 共享总线
  • 间接连接

image-20231212150551499

节点建模

为节点建模

为处理器和设备建模

为系统的拓扑结构建模

  • 分布式系统
  • 客户机/服务器系统
  • 嵌入式系统
建模一般规则
  • 从系统的部署视图中辨别出物理的计算资源,把他们用节点表示
  • <<processor>>或<<device>>对其进行修饰
  • 必要的时候定义其他变体
  • 可以考虑为节点指定属性和操作

image-20231212151448975

为组件的部署建模

用节点来描述软件组件在具有特定拓扑结构的物理连接的各节点之间的分布

部署图建模一般规则
  • 将系统中各有意义的组件分配到相应节点
  • 考虑同一个组件在多个不同节点上的部署
  • 描述组件和节点的联系
    • 在节点的规格说明中描述,不出现在模型图上
    • 使用依赖关系连接组件和节点
    • 在模型图上讲节点包含的组件列在节点的一个单独的分隔区内。
  • 组件分配
  • 多节点部署
  • 联系描述
  • 节点分隔

image-20231212151740244