类图描述系统中类的静态结构,它不仅定义系统中的类,表示类之间的关系(如关联、依赖、聚集等),也表达类的内部结构(即类的属性和操作)。类图描述的这种静态关系涉及软件系统开发的整个生命周期。

7.1 类和对象

在面向对象的建模技术中,类、对象及它们之间的关系是最基本的建模元素。用类和对象表示现实世界,用消息和方法来模拟现实世界的核心思想。

7.2 寻找类

可以从用例图、事件流中找,也可以通过对象的共性来寻找。
类的三种类型:

  1. 实体类保存要放进永久存储体的信息。
  2. 边界类位于系统与外界的交接处,包括所有窗体、报表、打印机和扫描仪等硬件的接口以及与其他系统的接口。要寻找和定义边界类,可以检查用例图。每个角色和用例交互至,少要有一个边界类。边界类使角色能与系统交互。
  3. 控制类负责协调其他类的工作。每个用例通常都有一个控制类,来控制用例中事件的膨顺序。在交互视图中,控制类具有协调的责任。可能有许多控制类在多个用例间共用的情况。

    7.3 类图的组成

    系统中的各种概念是在现实应用中有意义的概念,这些概念包括真实世界中的概念、抽象的概念、实现方面的概念和计算机领域的概念。在大多数的UML模型中可以将这些概念的类型概括为以下4种,分别是:类、接口、数据类型、构件。UML还为这些类型起了一个特别的名字—-类元(Classifer)。

    7.3.1 如何用UML表示一个类

    image.png

    | 关键字 | 符号 | 语义 | | —- | —- | —- | | public | + | 允许在类的外部使用或查看该属性 | | protected | # | 经常和泛化关系等一起使用,允许子类访问父类中受保护类型的属性 | | private(默认) | - | 只有类本身才能够访问,外部—概访问不到 | | Implementation | | 仅仅在定义的包中才能够可见** |

  4. 类的名称(Name):每个类都有一个惟一的名称,通常采用CamelCase格式表示。类的名称的书写字体也有规范,正体字说明类是可被实例化的,斜体字说明类为抽象类。 在一些关于UML的书中,也可以将其表示成“Office::Printer”的形式,代表一个名称为Printer的类位于名称为Office的包中。

  5. 类的属性(Attribute):是已被命名的类的特性,它描述该类实例中包含的信息。
    • 语法:[可见性]属性名称[:属性类型] [=初始值][{属性字符串}] ,除了第一个英文单词外,其余单词的首字母要大写。如果属性是静态的,则加下划线,属性名称前面可以加”/”表示该性质的值是派生的,不是原始定义;属性类型后可以加”[ 多重性定义]”;

image.png

  • 初始值用来保护系统的完整性,为用户提供易用性;属性字符串是用来指定关于属性的一些附加信息,
  • 如某个属性应该在某个区域内是有限制的。任何希望添加在属性定义字符串中但又没有合适地方可以加入的规则都可以放在属性字符串中。 属性字符串表示该性质的多个修饰符,用逗号分开,有下面选择:
    • readOnly:表示只读,不可改。
    • Union:表示该属性是多个子集合的一个派生并集。
    • subsets<属性名> :该属性的值是指定属性的值的一个子集。
    • redefines<属性名>:属性是继承而来的某个属性的重定义。
    • Ordered:表示该属性的多个值是有序的。
    • Unique:表示该属性的多个值是唯一的、不重复的。
    • :用一个表达式来约束该属性的值。
      1. 类的操作(Operation) 是指类所能执行的动作,也是类的一个重要组成部分,描述了在软件系统中所代表的对象具备的动态部分的公共特征抽象。
  • 语法:[可见性]操作名称[(参数表)] [:返回类型][{属性字符串}] ,操作名称如果是静态的,则加下划线;如果是抽象的,则用斜体字表示;
  • 参数表参数的定义方式采用形式如: “[方向]名称:类型[=初始值][{属性字符串}]”,形参的方向:
    1. in表示一个输入形参,按值传递。这是默认方向。
    2. out表示一个输出形参,没有输入值,往往是空值。
    3. inout表示一个可改变的输入形参,操作中读取其值,也可改变输入的值,最终值对调用方是可用的。
  • 属性字符串
    • redefines<操作名>该操作是对继承而来的某个操作的重定义。
    • query该操作不会改变系统中对象的状态。
    • ordered表示返回的多个值是有序的。
    • unique表示返回的多个值不重复。
    • 作用于该操作的若干约束,如前置条件一、后置条件等。
      1. 类的职责(Responsibility)指的是对该类的所有对象所具备的相同的属性和操作共同组成的功能或服务的抽象。在声明类的职责时,可以非正式的在类图的下方增加一栏,将该类的职责逐条描述出来。
      2. 类的约束(Constraint)指定了该类所要满足的一个或多个规则。在UML中约束是用一个大括号括起来的文本信息
      3. 类的注释(Note)可以为类添加更多的描述信息,也是为类提供更多描述方式中的一种。

        7.3.2 接口和其它类

  1. 接口是在没有给出对象的实现和状态的情况下对对象行为的描述。通常在接口中包含一系列操作,但是不包含属性,并且它没有对外界可见的关联。在UML中,接口使用<>版型表示,也可以用一个带有名称的小圓圈来简化表示,并且可以通过一条Realize(实现关系)线与实现它的类相连接,如图所示。接口之间的泛化关系也是用类泛化关系所使用的符号表示 。

    image.png

  2. 抽象类是一种不能够被直接实例化的类,也就是说不能够创建一个属于抽象类的对象,接口则是一种类似于抽象 类的机制,它是一个没有具体实现的类。

image.png

  1. 关联类即是关联也是类,它不仅像关联那样连接两个类,而且还可以定义一组属于关系本身的特性。

image.png

  1. 模板类可以根据占位符或参数来定义类,而不用说明属性、方法返回值和方法参数的实际类型

image.png

  1. 主动类的实例称为主动对象,一个主动对象拥有一个控制线程并且能够发起控制活动;它不在别的线程、堆栈或状态机内运行,具有独立的控制期。从某种意义上说,它就是一个线程。
  2. 在诸如Java的语言中,允许你将一个类的定义放在另一个类定义的内部,这就是嵌套类,在Java中也称为内层类。嵌套类是声明在它的外层类中的,因此只能够通过外层类或外层类的对象对它进行访问。

    7.3.3 类之间的关系

  3. 依赖关系

    • 依赖表示的是两个或多个模型元素之间语义上的连接关系。要避免双向依赖。一般来说,不应该存在双向依赖。 | 依赖关系 | 功能 | 关键字 | | —- | —- | —- | | 绑定 | 为模板参数指定值,以生成一个新的模型元素 | bind | | 实现 | 说明和对这个说明的具体实现之间的映射关系 | realize | | 使用 | 声明使用一个模型元素需要用到已存在的另一个模型元素(包括了调用、参数、发送、实例化) | use | | 调用 | 声明一个类调用其他类的操作的方法 | call | | 参数 | 一个操作和它的参数之间的关系 | parameter | | 发送 | 信号发送者和信号接收者之间的关系 | send | | 实例化 | 关于一个类的方法创建了另一个类的实例的声明 | instantiate | | 跟踪 | 声明不同模型中的元素之间存在一些连接,但不如映射精确 | trace | | 精化 | 声明具有两个不同语义层次上的元素之间的映射 | refine | | 派生 | 声明一个实例可以从另一个实例导出 | derive | | 访问 | 允许一个包访问另一个包的内容 | access | | 输入 | 允许一个包访问另一个包的内容并为被访问包的组成部分增加别名 | import | | 友员 | 允许一个元素访问另一个元素,不管被访问的元素是否具有可见性 | friend |
分类 依赖关系 关键字
1.绑定Binding 绑定 bind
2.实现Realization 实现 realize
3.使用
Usage
使用 use
调用 call
参数 parameter
发送 send
实例化 instantiate
4.抽象
Abstraction
跟踪 trace
精化 refine
派生 derive
5.授权
Permission
访问 access
输入 import
友员 friend
  • 绑定( Binding)依赖只包含绑定关系一种。绑定是将数值分配给模板的参数。它是具有精确语义的高度结构化的关系,可通过取代模板备份中的参数实现。

image.png

  • 实现依赖指的是说明和对这个说明的具体实现之间的映射关系。
  • 使用依赖关系包含使用、调用、参数、发送和实例等:
    • 使用表示的是一个元素的行为或实现会影响另一个元素的行为或实现;
    • 调用表示一个类中的方法调用另一个类的操作;
    • 参数表示类中的一个操作和它参数之间的关系;
    • 发送表示一个类中的方法把信号发送到相关接收目标;
    • 实例表示一个类的方法创建了另一个类的实例。
  • 抽象(Abstraction)依赖用来表示客户与提供者之间的关系,依赖于在不同抽象层次上的事物,将同一个潜在事物的不同形式联系起来。抽象依赖关系包含跟踪、精化和派生等。
  • 授权(Permission)依赖用来表示一个事物对另外一个事物进行访问的能力。提供者通过设定客户类的相关权限控制和限制对其内容访问的方法。授权依赖关系包含访问、导入、友元等:
    1. 泛化关系
  1. 泛化关系用来描述类的一般和具体之间的关系。泛化关系描述的是“is a kind of”(是……的一种)的关系,它使父类能够与更加具体的子类连接在一起,泛化关系是使用从子类指向父类的一个带有实线的箭头来进行表示,指向父类的箭头是一个空三角形。
  2. 泛化关系的第一个用途是用来定义可替代性原则,即当一个变量(如参数或过程变量)被声明承载某个给定类的值时,可使用类(或其他元素)的实例作为值,这被称作可替代性原则(由Barbara Liskov提出)。
  3. 泛化的另一个用途是在共享父类所定义元素的前提下允许自身增加描述,这被称作继承。继承的方式有两种,分别是单继承和多继承。 泛化使得多态操作成为可能,即操作的实现是由它们所使用的对象的类而不是由调用者确定的。
    1. 关联关系
  4. 关联关系是一种结构关系,指出了一个事物的对象与另一个事物的对象之间的语义上的连接。一个类的关联的任何一个连接点都称为关联端,与类有关的许多信息都附在它的端点上。关联端有名称、角色、可见性以及多重性等特性。

image.png

  1. - 多重性:
  2. - 0 仅为0
  3. - 0..1 0个或1
  4. - 0..n 0个到无穷多个
  5. - 1 恰为1
  6. - 1..n 1到无穷多个
  7. - n 无穷多个
  8. - 3 3
  9. - 0..5 0-5
  10. - 5..15 5-15
  1. 关联的含义:通过属性来表示一个对象对另一个对象的静态依赖关系。
    1. 关联是对象间的;
    2. 关联是一种静态的关系,而不是通过操作。
  2. 关联的三种表现形式:
    1. 连接:—— 最弱的关联,表示两个类的对象之间有导航关系。
    2. 聚集:A◇——B 表示对象A包含一个对象B,聚合关系描述的是部分与整体关系的关联。重在集中在一起
    3. 组合:◆—— 强语义耦合,也是一种特殊的关联,也表示类之间整体和部分的关系,但是组合关系中部分和整体具有统一的生存期。一旦整体对象不存在,部分对象也将不存在。部分对象与整体对象之间具有共生死的关系。重在成为一体

7.4 类图绘制实例

小王是一个爱书之人,家里各类书籍已过千册,而平时又时常有朋友外借,因此需要一个个人图书管理系统。该系统应该能够将书籍的基本信息按计算机类、非计算机类分别建档,实现按书名、作者、类别、出版社等关键字的组合查询功能。在使用该系统录入新书籍时系统会自动按规则生成书号,可以修改信息,但一经创建就不允许删除。该系统还应该能够对书籍的外借情况进行记录,可对外借情况列表打印。另外,还希望能够对书籍的购买金额、册数按特定时间周期进行统计。
image.png
image.png