使用 PlantUML 画 UML(上)类图

简介: 大家平日在写技术文档时,往往都有画 UML 图的需要,PrecessOn 或者 darw.io 等来绘制 UML 勉强可用但是不够专业。这里为大家推荐一个专门画UML的工具: PlantUML

大家平日在写技术文档时,往往都有画 UML 图的需要,很多人使用 PrecessOn 或者 darw.io 等来绘制 UML ,勉强可用但是不够专业。这里为大家推荐一个专门画UML的工具: PlantUML

1. PlantUML

PlantUML 诞生于 2009 年,知道的人多但是使用的人少。因为它使用特殊的 DSL 进行画图,相较与其他工具,PlantUML 的图不是“画”出来的而是“写”出来的。

虽然有一定学习成本,但是却可以画出更专业的UML图,而且文本格式也便于保存。本文总结 PlantUML 的基本用法,帮助大家快速入门。

安装环境

PlantUML 是一个 java 程序,所以有 JDK 就能跑。可以从官网直接下载 jar 文件执行,当然它也提供了 IDEA 和 VSCode 的插件。

需要注意的是,PlantUML 的本地渲染依赖 Graphviz ,需要提前安装并配置环境变量。如果你使用 VSCode 插件,也可以借助云端渲染,只需要作如下配置:

之后就可以在 VSCode 中一边“写” UML 一边预览了。

接下来我们学习如何写出漂亮的 UML ,像学习其他语言一样 从 Hello World 开始。

2. Hello World

//hello.pu
@startuml
Hello <|-- World
@enduml

PlantUML 文件通常以 .pu 为后缀,

命令行指定 pu

java -jar plantuml.jar hello.pu

在当前目录下会将 @startuml@enduml 之间的部分生成生成同名的 png

除了.pu以外,各种源码文件中的 @startuml@enduml 也能识别并生成 png,
例如 .c.c++, .htm, .java 等等,因此我们可以将源码配套的 UML 写入到注释中:

/**
 * @startuml
 * class JavaSource {
 *   - String message
 * }
 * @enduml
 */
public class JavaSource {}

需要注意,一组@startuml/@enduml 对应一张 png,如果一个文件中有多组,则生成的 png 文件名会添加自增数字后缀。 此外也可以紧跟在 @startuml 之后指定文件名

@startuml foo
class Foo
@enduml

@startuml bar
class Bar
@enduml

@startuml baz
class Baz
@enduml

3. 基本语法

注释

单引号后面跟随的内容是注释

@startuml no-scale
' 这是注释
Hello <|-- World
@enduml

Title

title后跟标题

@startuml
title Hello Title
Hello <|-- World
@enduml

多行 title

titleend title 之间的输入可以换行

@startuml
title
Hello
Title
end title
Hello <|-- World
@enduml

标题样式

PlantUML 支持使用 Creole 这种标记语言,来丰富文字样式,Creole 的用法类似 markdown。

参考 : https://en.wikipedia.org/wiki/Creole_%28markup%29
@startuml
title
* __Hello__
* **World**
end title
Hello <|-- World
@enduml

图注

caption之后跟的内容显示为图注

@startuml
caption 图1
Hello <|-- World
@enduml

header/footer

@startuml
header Hello
Hello <|-- World
footer World
@enduml

header footer可以在头部和尾部追加注释。 默认 header 右对齐, footer 居中对齐。

对齐方式

@startuml
left header Hello
Hello <|-- World
right footer World
@enduml

header footer 前加 left center right 可以设置对齐方式

多行 header/footer

title 一样, header ... end header , footer ... end footer

@startuml
header
Hello
Header
end header

Hello <|-- World

footer
World
Footer
end footer
@enduml

放大率

@startuml no-scale
Hello <|-- World
@enduml

@startuml scale-1.5
scale 1.5
Hello <|-- World
@enduml

@startuml scale-0.5
scale 0.5
Hello <|-- World
@enduml

scale 可以为UML设置防大率

4. 类图

Class

@startuml
class Hello
class World
@enduml

class 指定类

Interface

@startuml
interface Hello
interface World
@enduml

interface 指定接口

抽象类

@startuml
abstract class Hello
@enduml

abstract class 指定抽象类

枚举

@startuml
enum HelloWorld {
    ONE
    TWO
    THREE
}
@enduml

enum 指定枚举, { ... } 定义枚举值

类型关系

UML中类型之间有六大关系:

  • 泛化(Generalization)
  • 实现(Realization)
  • 关联(Association)
  • 聚合(Aggregation)
  • 组合(Composition)
  • 依赖(Dependency)

接下来逐一说明:

泛化

泛化关系就是类的继承,java 中对应 extends 关键字。

@startuml
Child --|> Parent
Parent2 <|-- Child2
@enduml

<|-- --|> 指定继承关系

实现

实现关系,对应 implements 关键字

@startuml
Plane ..|> Flyable
Flyable <|.. Plane
@enduml

..|>, <|.. , 圆点表示虚线

依赖

依赖表示使用关系,java中, 被依赖的对象/类, 以方法参数, 局部变量和静态方法调用的形式出现。比如, 厨师在烹饪的时候看了一眼菜谱, 厨师"使用"了菜谱, 照着它炒完菜后,这种使用关系就结束了(临时性).

@startuml
Chef ..> Recipe
@enduml

关联

关联关系,表示"拥有"。 相比依赖关系的临时性和单向性,关联关系具有长期性、平等性(可双向),所以关联表示的关系比依赖更强。比如现实生活中的夫妻, 师生等关系。长期存在并且是相互的关系。 此外关联可以表示一对一,一对多,多对一,多对多等各种关系。

@startuml
Address <-- Husband
Husband <--> Wife
Husband2 -- Wife2
@enduml

因为比依赖关系更强, 所以是实线+箭头。 双向关联可以省略箭头。

后面两种关系 "聚合" 和 "组合",都属于关联关系, 用来表示关联关系中整体与部分的关系。java 中 一个 Class 与其成员变量 Class 类型之间就是这种整体与部分的关联关系。

聚合

聚合关系相对于组合弱一些,整体与部分是可分离的。 比如部门与员工,部门有许多员工,员工离职了部门仍然存在,不受影响。反之部门解散了,员工可以去其他部门(整体与部分可分离)

@startuml
Department o-- Employee
@enduml

o 表示空心菱形

组合

组合关系中,整体与部分是不可分离的,整体与部分的生命周期保持一致,少了对方自己的存在无意义。例如人体是有四肢组成的,四肢不能脱离人体存在,人体少了四肢也难言完整

@startuml
Body "1" *-- "2" Arm
Body "1" *-- "2" Leg
@enduml

* 表示实心菱形

同时也看到了一对多时的数字表示方法,双引号" 包裹,放在线段与Class之间。 多对多也同样。

最后再总结一下六大关系

继承 实现 依赖 关联 聚合 组合
关系含义 功能扩展 功能实现 使用 拥有 整体-部分(has-a) 整体-部分(contains-a)
关系特性 - - 临时性,单向性 长期性,可双向(平等性) 整体与部分可分离 整体与部分不可分离,生命周期一致
java语法 extends implements 方法参数,局部变量,静态方法调用 成员变量 成员变量 成员变量
关系强弱 较强 较强 非常强
现实事例 父子 飞机/鸟可以飞 厨师使用菜谱 夫妻,师生 部门-员工 人体-四肢
图形指向 箭头指向父类 箭头指向接口 箭头指向被使用者 指向被拥有者,可双向 箭头指向部分, 菱形指向整体 箭头指向部分,菱形指向整体

综合运用

@startuml
interface One
interface Two
interface Three extends Two
interface Four
class Five implements One, Three
class Six extends Five implements Four {
    field: String
    method(): void
}
@enduml

成员变量、成员方法

@startuml
class Hello {
    one: String
    three(param1: String, param2: int): boolean
    String two
    int four(List<String> param)
}
@enduml

class定义后跟大括号,声明成员,然后按照 变量名:类型 的顺序声明,类型后置。方法和成员的顺序上可以混在一起,最终成图是,会自动分为两组

成员可见性

UML 使用以下符号表示可见性

Character Visibility
- private
# protected
~ package private
+ public

但是 PlantUML 将这种文字符合进一步图形化:

@startuml
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml

当然,也可以关闭这种图形化符合,继续使用文字符号

@startuml
skinparam classAttributeIconSize 0
class Hello {
    - privateField: int
    # protectedField: int
    ~ packagePrivateField: int
    + publicField: int

    - privateMethod(): void
    # protectedMethod(): void
    ~ packagePrivateMethod(): void
    + publicMethod(): void
}
@enduml

通过 skinparam classAttributeIconSize 0 关闭图形化符号

抽象方法

@startuml
class Hello {
    {abstract} one: int
    {abstract} two(): int
}
@enduml

成员前面加 {abstract} 标记位抽象成员

静态方法

@startuml
class Hello {
    {static} ONE: int
    {static} two(): int
}
@enduml

添加 {static} 表示静态方法

泛型

@startuml
class Hello<H>
class World<W> 
@enduml

类名后跟<泛型>

包图

@startuml
package one.two {
    class Hello
}

package three.four {
    World -- Hello
}
@enduml

package <name> {...} 中可以写类 UML 图

包图中的声明顺序

@startuml
package three.four {
    World -- Hello
}

package one.two {
    class Hello
}
@enduml

包图的顺序很重要,如上图 one.two 中的类被 three.four 依赖,所以应该写到先面, 以为 Hello 会声明在第一个出现的包中。

备注(note)

@startuml
class Fizz
note left: fizz

class Buzz
note right: buzz

class Foo
note top: foo

class Bar
note bottom: bar
@enduml

使用 note <top|bottom|left|right>: <备注> 为 UML 图添加备注, 备注内容可以是 Creole 语法

指定目标类

@startuml
Fizz -- Buzz
note left of Fizz: fizz
note right of Buzz: buzz
@enduml

note <位置> of <目标>: <备注>用来为指定目标 Class 生成备注

为类关系进行备注

@startuml
Fizz -- Buzz
note on link: fizz-buzz
note left: buzz
@enduml

note on link: <备注> 可以在类图的关系中添加备注

给备注加名字

@startuml
note "Hello World" as n1
Hello -- n1
World .. n1

note "Fizz Buzz" as n2
@enduml

note "<备注>" as <名字>用来给备注设置名字,有了名字后,可以通过名字将一个备注关联到多个Class

多行备注

@startuml
class Hello
note left
Hello
World
end note

Fizz -- Buzz
note on link
Fizz
Buzz
end note
note left of Fizz
fizz
buzz
end note

note as n1
Foo
Bar
end note
@enduml

end note 用来结束多行的备注

目录
相关文章
|
4月前
|
Java uml
使用工厂方法模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程序实
该博客文章通过UML类图和Java代码示例,展示了如何使用工厂方法模式设计一个支持加法、减法、乘法和除法运算的计算机程序,并严格按照类图设计实现程序。
|
4月前
|
Java uml
1、使用简单工厂模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程
该博客文章展示了如何使用简单工厂模式设计一个程序,该程序能够根据用户输入的运算符(加、减、乘、除)对两个数进行计算,并提供了相应的UML类图和Java源码实现。
1、使用简单工厂模式设计能够实现包含加法(+)、减法(-)、乘法(*)、除法(/)四种运算的计算机程序,要求输入两个数和运算符,得到运算结果。要求使用相关的工具绘制UML类图并严格按照类图的设计编写程
|
6月前
|
应用服务中间件 uml
【UML】软件工程中常用图:类图、部署图、时序图、状态图
【UML】软件工程中常用图:类图、部署图、时序图、状态图
907 1
|
4月前
|
数据可视化 Java uml
精通UML:从类图到序列图的实战指南
【8月更文第23天】统一建模语言(Unified Modeling Language, UML)是一种用于软件工程的标准图形化语言,它提供了一套工具来帮助开发团队可视化、构造和文档化软件系统。在UML中,类图和序列图是最常用也是最重要的两种图。类图用于描述系统的静态结构,而序列图则用于表示对象之间的交互和系统的动态行为。
233 5
|
4月前
|
设计模式 uml
设计模式常用的UML图------类图
这篇文章介绍了UML中类图的基本概念和用途,详细解释了类与接口、类之间的关系,包括继承、实现、组合、聚合、关联和依赖等六种关系,并展示了它们在类图中的表示方法。
设计模式常用的UML图------类图
|
5月前
|
测试技术 uml
UML使用问题之如何在PlantUML中表示执行者与用例之间的关联
UML使用问题之如何在PlantUML中表示执行者与用例之间的关联
|
5月前
|
测试技术 uml
UML使用问题之什么是泛化关系,在PlantUML中如何表示
UML使用问题之什么是泛化关系,在PlantUML中如何表示
|
4月前
|
uml
UML 类图几种关系(依赖、关联、泛化、实现、聚合、组合)及其对应代码
UML 类图几种关系(依赖、关联、泛化、实现、聚合、组合)及其对应代码
567 0
|
7月前
|
数据可视化 Java uml
Java的UML类图
Java的UML类图
125 1
|
6月前
|
测试技术 uml
【UML】详解UML类图
【UML】详解UML类图
120 0