本文已参与「新人创作礼」活动,一起开启掘金创作之路。
1 说明
关于PlantUML的背景知识已经在程序员画图的正确姿势 | PlantUML(一)文章做了说明,这一篇主要讲解PlantUML的语法部分。语法部分会分为两篇文章来介绍,本篇文章会介绍序列图 (Sequence Diagram)、用例图 (Use Case Diagram)、类图 (Class Diagram)、活动图 (Activity Diagram)、组件图 (Component Diagram) 等图表的画法,其它的图表画法会在下一篇文章介绍。
2 PlantUML语法
如背景一章所述,PlantUML
所支持的图表非常丰富,语法种类也挺多。为了叙述方便,PlantUML语法将以图表种类为单位进行讲解。分一个图表,一个小章节来叙述。叙述的方式是,直接先显示一张完整的图表出来,然后再讲解这张图片的完整画法,增强实战性,在实战中学习PlantUML语法。
在PlantUML
工具绘图中,所有的描述语言都是用@startuml
和@enduml
分别作为开始和结尾。在@startuml
后面紧接着加上标记语法!theme amiga
,可以更改导出图片的渲染主题,其中amiga
为主题名。总共默认的主题有amiga
、aws-orange
、black-knight
、bluegray
、blueprint
、cerulean-outline
、cerulean
、crt-amber
、crt-green
、cyborg-outline
、cyborg
、hacker
、lightgray
、mars
、materia-outline
、materia
、metal
、mimeograph
、minty
、plain
、sandstone
、silver
、sketchy-outline
、sketchy
、spacelab
、superhero-outline
、superhero
、toy
、united
、vibrant
。这么多主题,总有一款适合你,并且github
上面还有其它开源主题。PlantUML
工具描述语言的一般范式如下:
@startuml
!theme amiga
'具体图片的描述语言'
@enduml
注意: 上面所述的每一种PlantUML
支持的图形其描述语言都不相同(不要被吓到,都很相似,触类旁通)。所以到了哪一种图形就用哪一种描述语言,不要弄“串”了。
2.1 序列图 (Sequence Diagram)
序列图主要用于按照交互发生的一系列顺序,显示对象(例如线程、进程)之间的这些交互行为。序列图是由对象(Object)、生命线(Lifeline)、激活(Activation)、消息(Messages)、分支与从属流等元素构成。一个典型的序列图和其对应的描述语言如下所示:
@startuml
participant User
User -> A: DoWork
activate A#FFBBBB
A -> A: Internal call
activate A #DarkSalmon
A -> B: << createRequest >>
activate B
B -> C: DoWork
activate C
C --> B: WorkDone
destroy C
B --> A: RequestCreated
deactivate B
deactivate A
A -> User: Done
deactivate A
@enduml
- 用
->
来绘制对象(例如线程、进程)之间传递的消息。使用-->
绘制一个虚线箭头; - 在一组
->
指向的后面跟一个冒号:
,冒号后面写一些对消息的具体描述,如DoWork
(冒号后面空一格再写描述); - 关键字
activate
和deactivate
用来表示对象的生命活动; destroy
表示一个参与者的生命线(垂直的虚线)的结束,如destroy C
将对象C打上大红叉,表示结束;- 在激活一个对象的时候,可以在后面加上颜色属性,如
activate A#FFBBBB
,激活对象A时变成红色,达到醒目效果; - 可以使用嵌套的生命线,如
A -> A: Internal call
,在激活后,也可以修改颜色如activate A #DarkSalmon
。
2.2 用例图 (Use Case Diagram)
用例图 是指从用例的角度描述系统的功能需求,它是系统预期功能(用例)及其环境(参与者)的模型。用例能够将系统需要与系统如何满足这些需求相关联。用例图是由 参与者(Actor)、用例(Use Case) 以及它们之间的关系构成。它是一个非常强大的计划工具,所以团队成员通常在开发周期的所有阶段都使用用例模型。一个典型的用例图及其描述语言如下所示:
@startuml
@startuml
left to right direction
actor 消费者
:收银员:
rectangle 结算用例 {
消费者 -- (结算)
(结算) .> (支付) : <<include>>
(帮助) .> (结算) : <<extends>>
(结算) -- 收银员
}
@enduml
--
表示横线,..
表示虚线;- 用
actor
关键字来定义参与者,如:actor 消费者
; - 也可以用两个冒号包裹起来定义参与者,如:
:收银员:
; - 用圆括号括起来表示用例,如:
(结算)
; - 使用
rectangle
或package
关键字,可以对参与者或用例进行分组,如:rectangle 结算用例
,包含结算、支付、帮助三个用例; - 带
<<include>>
的描述表示用例的包含关系。包含关系指用例可以简单地包含其他用例具有的行为,并把它所包含的用例行为作为自身行为的一部分。如(结算) .> (支付) : <<include>>
,结算用例包含支付用例的行为; - 带
<<extends>>
的描述表示用例的扩展关系。就是把新的行为加入到已有的用例中,如(帮助) .> (结算) : <<extends>>
,在结算用例中新扩展了帮助用例的行为; left to right direction
命令改变图示方向,也可以用top to bottom direction
。
3.3 类图 (Class Diagram)
类图是一切面向对象方法的核心建模工具。该图描述了系统中对象的类型以及它们之间存在的各种静态关系。它既用于应用程序的系统分类的一般概念建模,也用于详细建模,将模型转换成编程代码。
@startuml
Object <|-- ArrayList : extension
ArrayList *-- Transform : contains
ArrayList o-- StateCalculation : aggregation
class Object {
-field1
#field2
~method1()
+method2()
}
class ArrayList {
#Object[] elementData
~int size()
+int length()
{static} String id
{abstract} void methods()
}
class Transform {
}
class StateCalculation {
}
@enduml
- 使用关键字
class
申明一个类,如:class Object
、class ArrayList
; - 类之间的
Extension(扩展)
、Composition(组合)
、Aggregation(聚合)
关系,分别用<|--
、*--
、o--
来进行标记,如:Object <|-- ArrayList : extension
标记两个类之间的扩展关系。在渲染出来的图片中可以看出都有特别的形状对它们进行区分; - 在关系之间使用标签来说明时, 使用冒号
:
后接标签文字,如:ArrayList *-- Transform : contains
; - 声明字段 (对象属性)或者方法。可以使用
{}
把字段或者方法括起来。 - 定义可访问性。
private
、protected
、package private
、public
这些可访问性质用-
、#
、~
、+
来标记。在渲染出来的图片中可以看出都有特别的形状对它们进行区分; - 抽象与静态。通过修饰符
{static}
或者{abstract}
,可以定义静态或者抽象的方法或者属性。如:{static} String id
、{abstract} void methods()
。
2.4 活动图 (Activity Diagram)
活动图是工作流的图形化表示。活动图主要由活动和动作构成,也可以支持分支选择、迭代、并行。活动图主要用于为计算性和组织性过程(即工作流)建模。活动图主要是用来说明控制流。典型的活动图和其描述语言如下:
@startuml
title Servlet Container
(*) --> "ClickServlet.handleRequest()"
--> "new Page"
if "Page.onSecurityCheck" then
->[true] "Page.onInit()"
if "isForward?" then
->[no] "Process controls"
if "continue processing?" then
-->[yes] ===RENDERING===
else
-->[no] ===REDIRECT_CHECK===
endif
else
-->[yes] ===RENDERING===
endif
if "is Post?" then
-->[yes] "Page.onPost()"
--> "Page.onRender()" as render
--> ===REDIRECT_CHECK===
else
-->[no] "Page.onGet()"
--> render
endif
else
-->[false] ===REDIRECT_CHECK===
endif
if "Do redirect?" then
->[yes] "redirect request"
--> ==BEFORE_DESTROY===
else
if "Do Forward?" then
-left->[yes] "Forward request"
--> ==BEFORE_DESTROY===
else
-right->[no] "Render page template"
--> ==BEFORE_DESTROY===
endif
endif
--> "Page.onDestroy()"
-->(*)
@enduml
- 使用
(*)
作为活动图的开始点和结束点,用-->
绘制箭头。如:(*) --> "ClickServlet.handleRequest()"
和-->(*)
,分别作为上面活动图的开始和结束; - 关键字
title
标识活动图的标题,如:title Servlet Container
标记上面活动图的标题; - 使用关键字
if/then/else
创建分支。和编程语言中的if else
逻辑一样,可以嵌套使用。 - 可以使用
== code ==
来显示同步条(就是水平粗线,将一条转移分为多个并发执行的分支,或将多个转移合为一条转移)。如:-->[yes] 。===RENDERING===
2.5 组件图 (Component Diagram)
组件图描绘了组件如何连接在一起以形成更大的组件或软件系统。它展示了软件组件的体系结构以及它们之间的依赖关系。组件图中通常包括组件、接口,以及各种关系。如下为组件图的一个样例和其描述语言。
@startuml
package "Some Group" {
() "HTTP" as HTTP
HTTP - [First Component]
[Another Component]
}
node "Other Groups" {
() "FTP" as FTP
FTP - [Second Component]
[First Component] --> FTP
}
cloud {
[Example 1]
}
database "MySql" {
folder "This is my folder" {
[Folder 3]
}
frame "Foo" {
[Frame 4]
}
}
[Another Component] --> [Example 1]
[Example 1] --> [Folder 3]
[Folder 3] --> [Frame 4]
@enduml
- 使用关键字
component
或是中括号[]
定义一个组件,如:[First Component]
; - 使用关键字
interface
或是圆括号()
定义一个接口,如:() "HTTP" as HTTP
; - 各元素(如接口、组件)之间使用虚线
..
、直线--
、箭头-->
进行连接。如:[Another Component] --> [Example 1]
; - 使用关键字
package
,node
,folder
,frame
,cloud
,database
将多个组件和接口组合在一起。
3 小结
本篇文章主要介绍了序列图 (Sequence Diagram)、用例图 (Use Case Diagram)、类图 (Class Diagram)、活动图 (Activity Diagram)、组件图 (Component Diagram) 等图表的画法,其它的图表画法会在下一篇文章介绍,敬请期待!