UML类图详解

符号表示

类(Class)

图示:

image-20240718203404217

访问修饰符写法:

  • private: -

  • public:+

  • protected:#

  • default:(什么都不写默认是default)

属性写法:

  • 属性名 :属性类型

方法写法:

  • 方法名(参数类型):返回类型

包(Package)

图示:

image-20240718203424137

接口(Interface)

图示:

image-20240718203439655

写法:

的写法

依赖(Dependency)

表示一个实体(或者说是一个元素)的实现或者行为依赖于另一个实体的定义。

依赖通常是非长期的,非结构化的

使用场景:

  1. 临时使用:当一个类的方法操作或者作为参数传递了另一个类的对象时,可以说第一个类依赖于第二个类。但这种关系比较弱,只在特定的方法中或者特定的时间片段中存在。

  2. 局部变量:当一个类的方法内部创建了另一个类的对象,作为局部变量使用时。

  3. 方法的返回类型:当一个类的方法返回另一个类的对象时。

  4. 参数类型:当一个类的方法或构造函数接受另一个类的对象作为参数时。

图示:

image-20240718203504721

  • 使用带箭头的虚线来表示依赖

  • 箭头说明Use可写可不写

关联(Association)

表示实体之间的结构化关系,表明这些实体是互相连接的,是可以通过某个实体导航到另一个实体的

使用场景:

  1. 双向关联:当两个类的对象需要互相知道对方时,可以使用双向关联。例如,学生和课程之间的关系,学生需要知道自己选了哪些课程,而课程也需要知道哪些学生选了这门课。

  2. 单向关联:如果一个类的对象需要知道另一个类的对象,但反过来则不需要时,可以使用单向关联。例如,订单和客户之间的关系,订单需要知道是哪个客户创建的,但客户不一定需要知道订单的详细信息。

  3. 自关联:当类的对象需要与同一个类的其他对象建立关系时,可以使用自关联。例如,在组织结构中,一个员工可能是另一个员工的上司。

  4. 多重性关联:关联关系可以有多重性(Multiplicity),表示一个对象与另一个对象的关联个数。例如,在图书馆系统中,一个作者可以写多本书,但一本书通常只有一个主要作者。

  5. 角色关联:在关联关系中,可以为类的对象在关系中的角色命名。这有助于理解关系的语义。例如,在医院系统中,医生和病人之间的关系,医生角色可以是“治疗者”,病人角色可以是“接受治疗者”。

  6. 导航关系:关联关系可以指示导航性,即对象之间的关系是否是单向的还是双向的。导航性用箭头表示,指向知道关系的类的方向。

  7. 链接属性:在某些情况下,关联本身可以拥有属性。这些属性称为链接属性,用于描述关联的特性。例如,在学生选课系统中,除了学生和课程,还可能有选课记录作为链接属性,记录选课的时间和成绩等信息。

图示:

image-20240718203517907

  • 不指定方向的关联:没有箭头,这种情况下关联的方向不明确,通常意味着关联的双方都可能知道对方,但具体的交互细节并不在类图中表示。
  • 双向关联:不使用箭头或者两端都有箭头,表示两个类相互知道对方。
  • 单向关联:通常会有一个箭头指向被关联的类,表示关联的方向,即一个类知道另一个类,但反过来不一定。

聚合(Aggregation)

使用场景:

  1. 非排他性的部分:聚合关系表示部分对象可以同时属于多个整体对象。例如,一名学生可以同时注册多个课程,这里的课程和学生之间就可以用聚合来表示。

  2. 共享的部分:在聚合关系中,部分对象可以被多个整体对象共享。例如,多个图书馆可以共享同一本书的实例(假设是电子书可以多处访问的情况)。

  3. 生命周期的独立性:部分对象的生命周期不依赖于整体对象。也就是说,即使整体对象被销毁,部分对象也可以继续存在。例如,一台电脑(整体)包含有内存条(部分),即使电脑报废了,内存条仍可以被拆卸出来单独使用。

  4. 非紧密耦合的关系:聚合表示的整体和部分之间的耦合比组合(一种更强的整体-部分关系)要松散。整体对象可以管理部分对象,但部分对象并不是整体对象不可缺少的一部分。

图示:

image-20240718203528221

关联和聚合的区别与联系

在面向对象的设计中,聚合(Aggregation)和关联(Association)都是用来描述对象之间的关系的。

  • 关联(Association)是一种广义的二元关系,它描述了两个对象之间的结构化关系。关联可以是双向的,也可以是单向的。在关联关系中,两个对象是相互独立的,一个对象的生命周期并不依赖于另一个对象。例如,学生和课程之间就可以用关联来表示,表明学生可以注册多个课程,课程也可以被多个学生注册。

  • 聚合(Aggregation)是关联的一种特殊形式,它表示的是整体和部分之间的关系,但是部分可以脱离整体而单独存在。在聚合关系中,整体对象负责部分对象的生命周期,但部分对象离开整体对象后,仍然可以独立存在。在聚合关系中,通常存在一个容器和多个内容对象,容器负责内容对象的管理。在学生和课程的例子中,如果将课程看作是容器,学生是内容对象,可以用聚合来表示课程和学生的关系。

在实际应用中,如果课程和学生之间的关系不需要强调整体和部分的关系,仅仅是普通的相互注册关系,那么使用关联来表示是合适的。如果需要强调课程作为一个整体包含了多个学生,而学生作为课程的一部分可以独立于课程存在,那么使用聚合来表示更加合适。

在数据库设计或者编程实现上,这两种关系可能并没有太大的区别,通常都是通过在表中使用外键或者在对象中使用引用来实现。设计的关键是理解对象之间的关系,并选择最适合描述这种关系的方式。

组合/合成(Composition)

使用场景:

  1. 车辆类(Vehicle)和引擎类(Engine)之间的关系。引擎是车辆的一部分,如果车辆被销毁,引擎也会随之销毁。

  2. 房屋类(House)和房间类(Room)之间的关系。一个房屋包含多个房间,如果房屋被拆除,房间也不再存在。

  3. 图书馆与书籍:图书馆类(Library)和书籍类(Book)之间的关系。图书馆包含许多书籍,如果图书馆被关闭,书籍也会被处理掉。

  4. 树类(Tree)和叶子类(Leaf)之间的关系。叶子是树的一部分,如果树被砍倒,叶子也会随之枯萎。

  5. 计算机类(Computer)和组件类(Component)之间的关系。计算机包含多个组件(如CPU、内存等),如果计算机被销毁,组件也会随之失去意义。

图示:

image-20240718203541844

组合(Composition)和聚合(Aggregation)的区别

我们常说的聚合是指弱聚合,组合则是强聚合

组合是实现代码复用的一种方式,但它比继承(Inheritance)表达了更强的关系,因为它表示一种”包含”关系,而不是”is-a”关系。组合通常用于表示”has-a”关系,例如,汽车”has-a”引擎。

组合和聚合(Aggregation)都是关联(Association)的特殊形式,但聚合是一种弱关系,表示整体和部分之间可以独立存在,例如,一所学校和一个教师,学校(整体)和教师(部分)可以独立存在。

总结一下特点:

  • 组合(Composition):强关系,部分的生命周期依赖于整体。
  • 聚合(Aggregation):弱关系,部分可以脱离整体独立存在。

继承/泛化(Generalization)

使用场景:

见名知意,用于继承

图示:

image-20240718203557464

实现(Realization)

使用场景:

见名知意,用于实现

图示:

image-20240718203606161

完整示例展示

image-20240718203617599

说明:

  1. 车泛化出了卡车和轿车

  2. 卡车有大卡车实现和小卡车实现

  3. 轿车由轮胎、引擎、刹车组成

  4. 驾驶员依赖轿车

  5. 不同驾驶员聚合出了车队

  6. 驾驶员和驾驶证是双向联系

  7. 车队和员工是一对多的关系