【UML】UML类图

2023-12-17 12:07:24

简介

UML类图一般使用在精化阶段,表示类、接口及其关联,用于静态对象建模

类图的定义能从交互图中产生,类图和交互图的绘制往往交替进行,动态和静态视图互补。

UML用类图描述系统中的类,以及存在于他们之间的各种静态关系。类图用于静态对象建模。可以用一幅图概括(和理解)大部分常用类图表示法。下图中的大部分元素都是可有可无的(例如,+/-可见性、方法参数、分栏)。

类图表示法

1.属性

1.1 表示方式

可以用以下方式表示类元的属性:属性文本表示法、关联线表示法、或者是两者兼有。

下图展示了这三种表示法:

类图属性表示法

属性文本表示法的完整格式:

visibility name: type multiplicity = ``default` `{property-string}

示例:
+abc : int = 0 {readOnly}
  • visibility —— 公开(+) / 私有 (-)
  • type —— 属性类型
  • multiplicity —— 多重性
  • default —— 创建期间没有指定值时新创建对象的值
  • {property-string} —— 特性字符串,允许附加的属性性质

在这里插入图片描述

可见性 visibility

  • '+'表示 public,公开的
  • '-'表示 private,私有的
  • '~'表示 package,包 —— 不建议使用
  • '#'表示 protected,保护的 —— 不建议使用

多重性 multiplicity

多重性定义了类A有多少个实例可以和类B的一个实例关联
类图多重性表示法

2.操作

操作不是方法。方法是实现,操作是声明,其中包含名称、参数、返回类型、可能的前置和后置条件约束等。

完整定义形式

visibility name (parameter-list) : return-type {property-string}

示例:
+abc(parm1:string,parm2:string) : int {leaf}
  • visibility —— 公开(+) / 私有 (-)
  • parameter-list 是操作的参数列表。
  • return-type 是返回值的类型,如果有的话。
  • property-string 指应用到给定操作的性质的值,可以包含任何附加信息

注意:访问属性的get和set相关操作可以省略

3.关系

UML中的关系 —— 泛化(Generalization)、 实现(Realization)、关联(Association)、聚合(Aggregation)、组合(Composition)、依赖(Dependency)

其中聚合和组合都属于关联的特殊形式

3.1 泛化 (Generalization) 【空心三角】

UML对泛化的定义如下:泛化——普通的类元与特殊的类元之间的分类学关系。特殊类元的每个实例也是普通类元的间接实例。因此,特殊类元间接地拥有了普通的类元的特性。

简单来说,用来表示父类和子类之间的继承关系,在图上,使用【空心三角+实线】来表示。

父类 父类实例=new 子类();

class Dog:public Animal{};  
Animal * pAnimal=new Dog;

类图泛化关系

3.2 实现(Realization)【空心三角+虚线】

我们一般用来表示接口(一组操作的集合,只有操作声明没有实现)和类或者抽象类和具体类之间的实现关系,在图上,使用【空心三角+虚线】来表示。
类图实现关系

抽象类在类图中斜体,或者用{abstract}标记表示
终止类不再具有抽象函数,不能被子类复写,加上{leaf}标记

补充:接口和抽象类的区别

1、抽象类允许包含某些方法的实现,而接口是不允许的,只能声明。

2、在抽象类中提供成员方法的实现细节。

3、抽象类中的成员变量可以实现多个权限public、private、protected、final等。

4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。

5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。

6、抽象类里可以没有抽象方法

7、如果一个类里有抽象方法,那么这个类只能是抽象类

8、抽象方法要被实现,所以不能是静态的,也不能是私有的。

9、接口可以继承接口,并且可多继承接口,但类只能单一继承。

10、接口可以通过匿名内部类实例化。接口是对动作的抽象,抽象类是对根源的抽象。抽象类表示的是,这个对象是什么。而接口表示的是,这个对象能做什么。

简单举例:
1、抽象类是对事物的抽象,即对类抽象接口是对行为抽象,即局部抽象
飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly(),然后Airplane和Bird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。
从这里可以看出,继承是一个"是不是"的关系,而接口实现则是"有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

2,抽象类是多个子类的像类,是一种模板式设计;接口是行为规范,是一种辐射式设计

例子:最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和pptC公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和pptC进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。
也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动

3.3 关联(Association) 【箭头】

表示类与类之间的连接,使得一个类知道另一个类的属性和方法(一个代码表现为友元),方向可以是单向,也可以是双向的,用来表示比较强的、长期的关系。在图上,使用【实线箭头】来表示,如下图人与氧气的关系。

代码体现:
1)B 作为 A 的属性出现在 A 中;
2)关联类A 引用了 被关联类B 的全局变量;

  public class Company  
  {  
     private Employee employee()  {  
         return employee;  
     }  
     public void setEmployee(Employee employee)   {  
         this.employee=employee;  
     }    
     public void run()  {  
          employee.starWorking();  
     }   
  }

类图的关联与依赖关系

  • 单向关联
    对于一个单向关联来说也是两个类是相关的,但是只有一个类知道这种联系的存在

如这里表示一个人可以关联0或多个account,且只有Person知道这种关联,并且Account可能作为属性出现在Person中,Person很可能引用Account的全局变量id

  • 双向关联(标准)
    对于双向关联来说被关联的两个类可以感知对方的存在

类图多重性表示法

双向关联是一对性质,它们从两个方向连接在一起。例如,Car有性质owner,Person有性质cars。使用双向箭头更容易突出双向连接的关系。编程语言实现双向关联关系的维护比较复杂,一般在关联的一端维护,如果是1对多的关联,在多的这一端维护

或者

3.4 聚合(Aggregation)【空心菱形】

聚合是关联关系的一种,聚合主要描述整体与部分直接的关系。需求陈述中常使用“包含”、“组成”、“分为…部分”等字句。除了基本(一般)聚集之外,还有共享聚集和组合聚集。

在聚合关系中,成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立存在

两个对象是可以分开实例化,然后通过相互引用,形成的关联关系

在UML中,聚合关系用带 空心菱形 的直线表示,一般是部分指向整体

  public class Computer   {  
     private CPU cpu;  
     public CPU getCPU()   {  
        return cpu;  
     }  
     public void setCPU(CPU cpu)   {  
          this.cpu=cpu;  
     }  
     //开启电脑  
    public void start()  {  
         cpu.run();
     }
  }

3.5 组合(Composition) 【实心菱形】

关联关系中的一个特例,此时,整体和部分是不分离的,组合关系,必须满足 “独占/无分享” 规则

聚合关系是“has-a”关系,组合关系是“contain-a”

两个对象是同时实例化的,在实例化的时候,就已经完成相互引用,形成的关联关系,如果整体的生命结束,部分的生命也要结束

在UML中,聚合关系用带 实心菱形 的直线表示,一般是部分指向整体

  class Arm();  
  class Person  {  
    Leg mLeg;  
    Arm mArm;  
  };

类图的组合关系

3.6 依赖(Dependency) 【箭头+虚线】

依赖即一个类的实现需要另一个类的协助,这种关系是具有偶然性的、临时性的、非常弱的。代码体现为:局部变量、方法的参数或者对静态方法的调用。

表示类与类之间的联系,使得一个类依赖于另一个类的定义,方向是单向的,用来表示比较弱的、临时的关系。

uml中使用一条箭头的虚线,从依赖方指向被依赖的类,使用【虚线箭头】来表示。

代码体现:
1)A方法的参数是B (耦合);
2)A方法的参数是B的属性(紧耦合);
3)A方法中实例化了B
4)A方法的返回值是B

一句话总结,就是A在方法中使用了B

 class Car();  
 class Hourse();  
 class Person  {  
   void buy(Car car)  {}  
   void buy(House pHouse)  {}  
 }

注意:尝试展示类图中的所有依赖是吃力不讨好的;因为有太多依赖而且改变太频繁。只有当依赖直接和你要沟通的特定主题相关时,才有选择地展示它们。

4、其他

4.1 注解符号

UML注解符号显示为摺角矩形,并使用虚线连接到要注解的元素上。注解符号可以表示多种事物,例如:

  • UML注解或注释
    UML注解或注释
  • 定义方法体

定义方法体

  • UML约束,必须使用“{…}”将它括起来(详见4.3图)

4.2 关键词

关键字含义用法示例
《actor》类元为参与者在类图中,置于类元名称之上
《interface》类元为接口在类图中,置于类元名称之上
{abstract}抽象元素;不能实例化在类图中,置于类元名称或操作名称之后
{ordered}具有强制顺序的一组对象在类图中,置于关联的端点

4.3 UML扩展机制

构造型(衍型stereotype)

构造型用来定义一些特定于某个领域或某个系统的构造块。用来扩展建模元素,增加建模元素的语义。构造型表示对现有建模概念的精化,并且定义在UML 的简档之中。

构造型是用来指出其他模型元素的用途的模型元素。UML 提供了一组可以应用于模型元素的标准构造型。

可以使用构造型来精化模型元素的含义。例如,可以对工件应用 ?library? 构造型以指示它是一个特定类型的工件。可以对使用关系应用 ?call?、?create?、?instantiate?、?responsibility? 和 ?send? 构造型,以准确指示一个模型元素如何使用另一个模型元素。还可以使用构造型来描述含义或用法不同于另一个模型元素的模型元素。

构造型可以具有称为标注定义的属性。将一个构造型应用于模型元素时,属性的值称为标注值。

标记(tag)

声明构造型时使用属性语法声明一组标记

约束(constraint)

约束以花括号之间的文本表示,例如{size>=0}。其中的文本可以是自然语言或其他语言。显示约束的三种方式如下图:

UML约束

简档(profile)

简档是一组相关构造型、标记和约束的集合,其目的是使用 UML 专用于特定领域或平台。UML 预定义了大量构造型,同时允许用户自行定义构造型,因此,在 UML 中构造型提供了扩展机制。

4.4 特性字符串

用来表示元素的特性。采用{name1=value1, name2=value2}的形式,例如{abstract, visibility=public}。

有些特性没有值,例如{abstract},这通常表示布尔类型的特性,是{abstract=true}的简写。注意,{abstract}既是约束,也是特性字符串。

另外,只读可表示为 {readOnly};冻结(不可变),可表示为 {frozen} 、 {final}。

4.5 单实例类

单实例类的含义是类实例化后只存在一个实例,永远不会有第二个。在UML图中,可以在类框中名称分栏的右上角标记“1”来表示这种类。

文章来源:https://blog.csdn.net/m0_51371693/article/details/125057089
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。