graphviz画UML类图

说到画图,我们可能首先想到photoshop 这样的工具,不一定人人都是学美术的,但是作为程序员,偶尔画个图,以方便更好的表达技术,那是很常有的事情,实际上画图的工具很多很多。这里,我要介绍一种和他们都不一样的工具, graphviz。

What is Graphviz?

Graphviz is open source graph visualization software. Graph visualization is a way of representing structural information as diagrams of abstract graphs and networks. It has important applications in networking, bioinformatics,  software engineering, database and web design, machine learning, and in visual interfaces for other technical domains. 

 

这段话来自 www.graphviz.org  官网。这里定义的很多,graphviz是一个开源做图软件,她能画结构化的抽象和网络图形,在网络,生物信息学,软件工程,数据库和web设计,机器学习, 可视化接口等众多其他技术领域都有应用。

 

这里也说明了,你要是想画一副《蒙娜丽莎》,那是不太可能了。我这里也只是使用她来画我们熟悉的UML类图。

 

关于graphviz,你可以从他的官网得到所有信息,所以这里,我们主要是注重如何用它来实现UML类图。如果你对其他图形感兴趣,可以随便一搜索,可以得到一大堆让你惊讶的东西。

graphviz有很多布局方式,我们常用的是DOT,有层级的有向图布局方式。

接下来就是准备工作:

扫描二维码关注公众号,回复: 718266 查看本文章

操作系统:windows

编辑器:gvim

程序下载:http://www.graphviz.org/Download_windows.php

就这些足矣。之所以用gvim,这里有个技巧待会再说。

 

gvim只是windows下的vim,我们可以不用,使用文本编辑器即可。

打开文本编辑器:输入

 

digraph G {
}

 这就定义了一个图。注意 digraph 是规定。必须这么写。

接下来,我们要定义图形中的元素,对于UML类图,类都是矩形,不是圆的。所以接下要定义节点:

digraph G{
    node[shape=record]
}

 node就是图中节点,保留关键字,shape表示形状,record是一种形状,就是矩形方块。中括号表示对node的定义。

接下来便可以定义具体的类了。这里我们来画一个UML的策略模式。也就是Strategy模式的UML

一个策略是包含在上下文Context中的,这样Contex改变了,那么策略也就变了。也就是锦囊妙计不是随便用,而是根据环境来用。Context中有调用策略的方法strategy,可能还有一些其他的方法,姑且称为contextInterface ,好了,基本这样,就可以写了

digraph G{
    node[shape=record]
    Context[
        label="{Context| +strategy : Strategy\l|+contextInterface()\l"}
    ]

 这里,对Context的定义,Context是用户自定义的节点(Context 写成什么没关系,label不能写错)。使用了node属性,其中的label属性是一个字符串,这里 | 表示换行 \l 也是空行的意思,占用一个空行。注意使用了{}把内容括起来。

接下来,我们定义策略接口Strategy,同时再定义几个具体不同策略的实现类。

digraph G {
    node[shape=record]
    Context[labell="{Context| +strategy : Strategy\l| +contextInterface()\l}"]
    Strategy[ label="{Strategy|\l|+algorithmInterface()\l}"]
    ca[label="{ConcreteStrategyA|\l|+algorithmInterface()\l}"]
    cb[label="{ConcreteStrategyB|\l|+algorithmInterface()\l}"]
    cc[label="{ConcreteStrategyC|\l|+algorithmInterface()\l}"]
}

  似乎快完成了。还差各个图形节点之间的关系。也就是类之间的关系。

关系很简单,我们只需这样

digraph G {  
    node[shape=record]  
    Context[label="{Context| +strategy : Strategy\l| +contextInterface()\l}"]  
    Strategy[ label="{Strategy|\l|+algorithmInterface()\l}"]  
    ca[label="{ConcreteStrategyA|\l|+algorithmInterface()\l}"]  
    cb[label="{ConcreteStrategyB|\l|+algorithmInterface()\l}"]  
    cc[label="{ConcreteStrategyC|\l|+algorithmInterface()\l}"]  
    
    Strategy -> Context
    ca->Strategy 
    cb->Strategy
    cc->Strategy

}

 可是对于UML图来说,这些连线是有特殊要求的,比如,继承是带空心箭头的实线,而Context和Strategy之间是聚合关系,棱形空心箭头。好吧,graphviz中是有对边的定义的。请看:

digraph G {    
    node[shape=record]    
    Context[label="{Context| +strategy : Strategy\l| +contextInterface()\l}"]    
    Strategy[ label="{Strategy|\l|+algorithmInterface()\l}"]    
    ca[label="{ConcreteStrategyA|\l|+algorithmInterface()\l}"]    
    cb[label="{ConcreteStrategyB|\l|+algorithmInterface()\l}"]    
    cc[label="{ConcreteStrategyC|\l|+algorithmInterface()\l}"]    
      
    edge[
        arrowhead="odiamond", style="filled"
    ]
    Strategy -> Context  

    edge[ arrowhead="onormal", style="filled"]
    ca->Strategy   
    cb->Strategy  
    cc->Strategy 

你也许想说,这也太简单了。确实,如果你想看看还有些什么shape,什么style可以去graphviz的官网一查便知。于是,我们像,大概可以看看是什么效果了吧。

保存文件,打开命令提示符,使用命令

dot strategy.dot Tpng -o strategy.png && stragegy.png

dot是布局方式, T  是生成的图片模式 -o表示输出文件。

已经有模有样了,可是可能还和我们心中的不太一样。我们希望接口Strategy在顶端。

digraph G {    
    node[shape=record]   
    {rank=same;Conext;Strategy}
    Context[label="{Context| +strategy : Strategy\l| +contextInterface()\l}"]    
    Strategy[ label="{Strategy|\l|+algorithmInterface()\l}"]    
    ca[label="{ConcreteStrategyA|\l+algorithmInterface()\l}"]    
    cb[label="{ConcreteStrategyB|\l+algorithmInterface()\l}"]    
    cc[label="{ConcreteStrategyC|\l+algorithmInterface()\l}"]    
      
    edge[
        arrowhead="odiamond", style="filled"
    ]
    Strategy -> Context  

    edge[ arrowhead="onormal", style="filled"]
    ca->Strategy   
    cb->Strategy  
    cc->Strategy 
}

 这个rank是表示节点之间的关系,比如一上一下,或者一左一右,或者是相同的高度。

可惜还是不理想。这是,我们可以加个注释,对Context的document解释

digraph G {    
    node[shape=record]    
	{rank=same;Context;Strategy}
    Context[label="{Context| +strategy : Strategy\l| +contextInterface()\l}"]   	docs[
	  style="filled", color="gold",	label="Strategy AlgorithmInterface()"
	] 
    edge [ arrowhead="none", style="dashed"]
    Context->docs
    Strategy[ label="{Strategy|\l|+algorithmInterface()\l}"]    
    ca[label="{ConcreteStrategyA|\l+algorithmInterface()\l}"]    
    cb[label="{ConcreteStrategyB|\l+algorithmInterface()\l}"]    
    cc[label="{ConcreteStrategyC|\l+algorithmInterface()\l}"]    
      
    edge[
        arrowhead="odiamond", style="filled"
    ]
    Strategy -> Context  

    edge[ arrowhead="onormal", style="filled"]
    {rank=same;ca;cb;cc;docs}
    ca->Strategy   
    cb->Strategy  
    cc->Strategy 
}

 注释背景是金色的。终于,我们的UML画出来,看起来是不是和你想像的一样呢?



 

好了,现在讲讲为什么用gvim,首先在windows下,gvim很强大。如果是linux就直接用vim了

找到安装路径,例如: C:\Program Files (x86)\Vim

看到_vimrc 文件,打开,在末尾插入一句

noremap <F5> :!dot "%:p" -Tpng -o %:r.png && %:r.png <CR>

这里是吧F5键映射到 后面的语句了。<CR>便是换行回车。也就是说当你编辑好一个dot文本以后,就可以直接按F5,然后就帮你把你所想的图形描述转化成图片,并且用windows默认的图片浏览器打开。

方便吧。哈哈。

以上只是对类图的很简单的一个实现,如果你对graphviz感兴趣,那么就赶紧动手吧。

猜你喜欢

转载自airu.iteye.com/blog/1900573
今日推荐