简介

平时需要画 UML 图,用的比较多的就是 StarUMLVisioRational Rose 。其中 StarUML 是跨平台的免费软件,相比其他的收费软件是个不错的选择。

今天要介绍的是PlantUML它是一个开源的用文字来描述的工具,简单来说就是用文字去写出各种 UML 图,而不是用鼠标去拖拽。上面介绍的工具都是通过鼠标去拖拽的方式去画出各种 UML 图。可能由于是个开发的缘故,天生就喜欢纯文本的东西,解析起来方便,占用内存小,改起来也方便,只要一个文本编辑器就可以改。当然我使用的原因是可以在 Emacs 中通过 Org Mode 结合 Org-Babel 使用,生成对应的 UML 图,所见即所得。

这里有一个在线体验的网址,有兴趣可以点击链接,前去体验。

安装

由于我用的 EmacsSpacemacs 所以我只要在 init.el 中加入如下配置,并下载好PlantUML的jar包放到家目录下,重启之后等待包安装好就可以用了。当然你还需要安装 Java 环境,毕竟这是个 Java 写的工具。

1
(setq-default dotspacemacs-configuration-layers '((plantuml :variables org-plantuml-jar-path "~/plantUml.jar")))

除了在 Emacs 中使用,也可以在其他文本编辑其中使用。比如: VimVSCodeSublimeNotepad++ 中使用。

类之间的关系

我们先来看一下类之间的关系在 PlantUML 中是怎么画的

关系 画法
继承 <|- -
实现 <|. .
依赖 <. .
关联 <- -
聚合 o- -
组合 *- -

我们就根据上表,来画一下类图。这里顺便提一下,如果要类之间的关系加上标识,可以在行尾加上 : 和标识。

由于使用到了中文所以要加上 -charset utf-8 不然中文会出现乱码,我们给当前的代码块指定一个输出的文件,以便查看。

所以 Org-Babel 要用如下格式,下文全部采用这种格式,就不在每个代码中列出了。

1
2
3
#+begin_src plantuml :file ./uml.jpg :cmdline -charset utf-8 :exports both
这里填写PlantUML的相关语句
#+end_src

来看一下类图之间的关系是怎么画的,写完之后使用快捷键 C-c C-c 来生成图片,如下图

1
2
3
4
5
6
7
8
@startuml
Class1 <|-- Class2 : 继承
Class1 <|.. Class2 : 实现
Class1 <.. Class2 : 依赖
Class1 <-- Class2 : 关联
Class1 o-- Class2 : 聚合
Class1 *-- Class2 : 组合
@enduml

可以看到在 PlantUML 中使用 @startuml 开始, @enduml 结尾,中间就是各个关系之间表示了。

成员变量和方法

看完了类之间关系的画法,来看看成员变量是怎么画的

方法一

通过在类名后面添加成员变量或者方法,使用 : 分割,系统会根据有没有 () 来判断是成员变量还是方法。

1
2
3
4
@startuml
ArrayList : Object[] elementData
ArrayList : void size()
@enduml

方法二

使用 {} 把成员变量和方法括起来,成员变量的类型可以写在字段名前面,也可以写在字段名后面,写在后面的要用 : 分割。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@startuml
class Dummy {
  String data
  void methods()
}

class Flight {
   flightNumber : Integer
   departureTime : Date
}
@enduml

方法三

显示的使用 {field} 来指定成员变量,或者 {method} 指定方法,不过不建议使用这种方式,这样会把成员变量和方法搞混。因为这样可以把字段设置为方法,也能把方法设置为字段。

1
2
3
4
5
6
@startuml
class Dummy {
  {field} A field (despite parentheses)
  {method} Some method
}
@enduml

可见性

Java 的都知道, Java 有访问属性, PlantUML 也为我们提供了这个功能,来画出访问属性。下面这张表就展示了它们是怎么画的。

字符 可见性
- private
# protected
~ package private
+ public
1
2
3
4
5
6
7
8
@startuml
class Visible{
 -field1
 #field2
 ~method1()
 +method2()
}
@enduml

如果不想用图形符号表示可见性,可以通过 skinparam classAttributeIconSize 0 来禁用

1
2
3
4
5
6
7
8
9
@startuml
skinparam classAttributeIconSize 0
class Visible{
 -field1
 #field2
 ~method1()
 +method2()
}
@enduml

抽象与静态的表示

除了可见性之外, Java 还有抽象类,静态方法。我们可以通过通过 {abstract} 来修饰抽象方法或属性。通过 {static} 修饰静态方法或属性。

1
2
3
4
5
6
@startuml
class Dummy {
  {static} String id
  {abstract} void methods()
}
@enduml

接口、注解、枚举的表示

除了类之外,还有接口、注解、枚举,它们分别用 interfaceannotationenum 表示

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@startuml
abstract class AbstractList
abstract AbstractCollection
interface List
interface Collection

List <|-- AbstractList
Collection <|-- AbstractCollection

Collection <|-- List
AbstractCollection <|-- AbstractList
AbstractList <|-- ArrayList

class ArrayList {
  Object[] elementData
  size()
}

enum TimeUnit {
  DAYS
  HOURS
  MINUTES
}

annotation SuppressWarnings
@enduml

包在 Java 中是一个重要的概念,我们不会把所有的类都放到一个包下面(简单的只有几个类除外),这就要求我们需要区分不同类来自哪个包。或者有一种情况是同名的类在不同的包中,有了包才能比较直观看出这个包有哪些类并且能够区分开。包在 PlantUML 中通过 package 关键字来标识。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@startuml
package "Classic Collections" #DDDDDD {
  Object <|-- ArrayList
}

package net.sourceforge.plantuml {
  Object <|-- Demo1
  Demo1 *- Demo2
}
@enduml

改变箭头的方向

使用文字来画 UML 图有一个很大的限制是不能直接拖拽它们之间的方向,这就需要提供摆放这些类位置的功能。 PlantUML 主要提供了如下两种方法。

方法一

类之间默认使用 -- 画竖线,画横线使用 -

1
2
3
4
@startuml
Room o- Student
Room *-- Chair
@enduml

我们可以调换 RommStudent 的顺序来达到摆放的目的。

1
2
3
4
@startuml
Student -o Room
Chair --* Room
@enduml

方法二

使用箭头内部关键字来改变方向,也就是上下左右了。

1
2
3
4
5
6
@startuml
foo -left-> dummyLeft
foo -right-> dummyRight
foo -up-> dummyUp
foo -down-> dummyDown
@enduml

备注

有时候我们想要对一个类或者其他东西加一些说明,备注一些信息,我们就会需要用到 PlantUML 的备注功能,下面介绍三种加备注的方法。

在类的末尾添加备注

我们可以在一个类的末尾通过 note left: xxx 为其添加一个在左边的备注。在上边、右边、下边分别是 note top: xxxnote right: xxxnote bottom: xxx 。这种方式比较适合只有一个方向上需要添加备注的,如果所有方向都需要备注使用这种方式其实会乱掉,它会相对前一条进行位置的摆放。

1
2
3
4
@startuml
class Foo
note left: 左边的备注
@enduml

为具体的类添加备注

UML 中的类有多个的时候,我们需要为某个具体的类添加备注,通过添加 note left of xxx 来在类的某个方向上添加备注。

1
2
3
4
5
6
7
8
9
@startuml
class Object

note left of Object : Object 左边的备注
note top of Object : Object 上边的备注
note right of Object : Object 右边的备注
note bottom of Object : Object 下边的备注

@enduml

浮动的备注

有时候我们可能需要一个独立的浮动备注,不和任何类相关,这时候可以使用 note 来表示。这里有一点需要注意的是最后面需要用 as xxx 取一个别名,不然会报错。

1
2
3
4
@startuml
class Foo
note "浮动的备注" as N1
@enduml

总结

UML 是一个工具,可以快速帮我们理清楚各个类之间的关系, UML 不止能画类图,还能画时序图、用例图、活动图,是一个非常方便的工具。本文所讲的 PlantUML 是一个用文本制作 UML 的程序,如果你喜欢纯文本不妨试试。

参考