统一建模语言的介绍和应用
统一建模语言概述
什么是UML
UML(Unified Modeling Language): 是一种为面向对象的产品进行说明、可视化和编制文档的一种标准语言。由1997年,Ration Software 公司的Rumbaugh 、Booch 和 Jacobson 的团队开发完成。经过实践,它在对大规模、复杂系统的建模方面,尤其是软件架构层次上卓有成效
UML图形介绍
-
结构形图形(Structure diagrams)强调的是系统式的建模
-
类图:描述了系统的类集合,类的属性和类之间的关系
class Person { Boolean sex Integer age void eat() void sleep() }
- 最上面是类名称
- 中间部分包含类的属性
- 底部部分包含类的方法
-
类的成员
+ public - private # protected ~ package (对包内其他成员可见)
-
类的关系
-
泛化(Generalization)指的是一个类(称为父类、父接口)具有另外的一个(或一些)类(称为子类、子接口)的共有功能。用带空心三角形箭头的实线表示。
class Person { Boolean sex Integer age void eat() void sleep() } class Man { + sing() - dance() # rap() ~ basketball() } Person <|-- Man
-
实现(Realization)指的是一个class类实现interface接口(可以是多个)的功能。用带空心三角形箭头的虚线表示。
class Car class Bus Car <|.. Bus
-
关联(Association)代表两个类之间、或类与接口之间一种强依赖关系,是一种长期的稳定的关系," … has a …"。
class Person class Clothes Person -- Clothes
-
依赖关系(Dependency)是一种比关联关系更加弱的关系,包含关联关系,可以简单的理解为一个类A使用到了另一个类B,“… uses a …”。用带燕尾箭头的虚线表示。
class ITMan { Computer computer } class Computer ITMan ..> Computer
-
聚合(Aggregate)是表示整体与部分的一类特殊的关联关系,较强于一般关联,没有了整体,局部也可单独存在。图形以空心的菱形箭尾与实线来表示
class Company class Staff Company o-- Staff
-
组成(Composition)表示整体与部分的包含关系。图形以实心的菱形箭尾与实线表示。
class Company class part Company *-- part
-
-
对象图:是实例 (Instance) 的表达,包括对象和数据值。静态的对象图是类图的一个实例,它是系统在某个时间点的详细状态的快照。
class Writer { String name; Integer age; } class Computer { String name; String memory; } Writer "0...n"--"0...n" Computer : 使用 object "liu writer" as a{ name = "liu" age = 24 } object "Computer1" as c1 { name = "内网" memory = "8G" } object "Computer2" as c2 { name = "外网" memory = "4G" } a -right-> c1 a --> c2
-
包图:显示包和包之间的依赖关系的结构性图表。
-
组件图:描绘了组件如何连接在一起以形成更大的组件或软件系统。它展示了软件组件的体系结构以及它们之间的依赖关系。
[Project] as p [Course] as c 项目信息 - p c --> 项目信息
-
部署图:表现用于部署软件应用的物理设备信息。
-
-
行为式图形(Behavior diagrams)强调系统模型中触发的事件
-
用例图:是用户与系统交互的最简表示形式,展现了用户和与他相关的用例之间的关系。它为“系统做什么”提供了简化了的图形表示,因此被誉为“搭建系统的蓝图”,让项目参与者明白系统要做成什么样。
-
活动图:用于展示工作流程,支持选择(Choice)、迭代(Iteration)和并发(Concurrency)
|author| start note left : initial node : open article; : publish; |mode rator| : mode rate; if (approval?) then(yes) : set status to published; stop else(no) : notify rejection; stop note right : activity final node
- 圆角矩形:表示“动作”;
- 菱形:表示“决策”;
- 粗实线:表示并行(并发性)活动的开始(分离)和结束(汇合);
- 黑圆:工作流的开始(初始节点);
- 黑圈套住的黑圆:工作流的结束(结束节点)。
-
状态图:描绘允许的状态和转换以及影响这些转换的事件,它有助于可视化对象的整个生命周期,从而更好地理解以状态主导的系统。
-
活动图和状态图的区别
活动图 状态图 对一个对象的某一系列活动进行组合描述。活动图是状态图的一种特殊形式 描述对象在其生命期中的行为状态变化 系统流程内部的处理流程驱动 外部事件的参与
-
-
交互性图形(Interaction diagrams),属于行为图形的子集合,强调系统模型中的资料流程
-
序列图:展示了在用例的特定场景中,对象如何与其他对象交互。
序列图中会绘出许多同时存在的不同物件(以垂直线表示,线的开始及结束为生命线,表示物件的产生及结束),而物件之间横向的箭头,表示物件之间交换的讯息,会以发生的先后顺序来排列。
// TODO 添加之前画的示例 -
协作图:也用于模拟用例的动态行为。与时序图相比,更侧重于显示对象的协作而不是时间顺序。
-
UML的发展
在抽象的编程语言发明之后,随着软件规模变大,软件系统越来越复杂,软件开发人员如何交流彼此的工作成了问题。
- 1991年,勒布朗发明了对象建模技术OMT-最适合分析数据密集型信息系统
- 1992年,雅各布森创造了面向对象软件工程OOSE。
- 1994年,布区发明了Booch方法
在1994年之后,为了统一建模语言的标准,勒布朗加入了 Rational Software 公司,和布区并肩作战,于1995年10月发布了第一个公开版本 UM 0.8。
之后于1995年,雅各布森加入Rational,经过三人的共同努力,于1996年6月和10月分别发布了两个新的版本,即UML 0.9和UML 0.91,并将UM重新命名为UML。Rumbaugh,Booch 和 Jacobson 的团队则被称为“UML三友”
到了1996年,OMG(Object Management Group)发布征求建议书(RFP),一些公司和组织,比如:DEC、HP、IBM、Microsoft、Oracle、Rational Software等成立了UML成员协会,以完善、加强和促进UML的定义工作。并且在1997年1月发布了UML1.0交由OMG管理。
UML的目标
UML建立旨在帮助软件开发人员改善软件生产流程、提高质量、降低成本并缩短产品上市时间。
主要有:
- 为用户提供现成的、有表现力的可视化建模语言,以便他们开发和交换有意义的模型
- 为核心概念提供可扩展性 (Extensibility) 和特殊化 (Specialization) 机制
- 独立于特定的编程语言和开发过程
- 鼓励面向对象工具市场的发展
- 支持更高层次的开发概念,如协作,框架,模式和组件
UML的优缺点
优点:
UML语言使得系统建模过程标准化、统一化和规范化,它采用图形化的表现形式,使产生的模型易于理解,方便开发人员和开发人员之间,开发人员和用户之间的沟通,从而即时得到反馈信息。
缺点:
“上不着天、下不着地、一盘散沙”:
(1)“上不着天”这种隔阂使建模结果无法与用户沟通确认所谓的需求,埋下了软件危机的祸根;
(2)“下不着地”这种隔阂使千辛万苦得到的建模结果无法指挥程序员编码,最后得到的软件与用户期望的结果很远,返工、误工、烦恼无穷;
(3)“一盘散沙”这种隔阂让建模图形之间的关系凌乱不堪,建模过程千辛万苦,建模结果很难自圆其说。
UML工具介绍
1.plantUml
-
类图
关系类型 符号 泛化关系 –|> 实现关系 …|> 关联关系 – 依赖关系 …> 组合关系 –* 聚合关系 –o @startuml Abstract class Animal { + eat(String food) } class Food class Bird note left : 鸟类 class Chicken Interface Fly class Crowd class Wings Animal <|-- Bird : 泛化 Bird <|-- Chicken : 泛化 Animal .right.> Food : 依赖 Chicken .left.|> Fly : 实现 Chicken "n" o-- "1" Crowd : 聚合 Chicken --* Wings : 组合 Chicken -right- Coop : 关联 @startuml
Abstract class Animal { + eat(String food) } class Food class Bird note left : 鸟类 class Chicken Interface Fly class Crowd class Wings Animal <|-- Bird : 泛化 Bird <|-- Chicken : 泛化 Animal .right.> Food : 依赖 Chicken .left.|> Fly : 实现 Chicken "n" o-- "1" Crowd : 聚合 Chicken --* Wings : 组合 Chicken -right- Coop : 关联
-
活动图
-
简单活动图
@startuml start : hello world; : good bey; stop @enduml
如下图:
start : hello world; : good bey; stop
-
条件判断
@startuml start : 操作; if (是否操作成功) then (是) : 返回操作结果; stop else (否) end endif @enduml
如下图:
start : 操作; if (是否操作成功) then (是) : 返回操作结果; stop else (否) end endif
-
条件选择
@startuml start switch (可选) case (case1) : 查询; : 输入标题; if (是否查询成功?) then (是) : 返回查询结果; else (否) end endif case (case2) :修改; case (case3) :删除; case (case4) :添加; endswitch stop @enduml
如下图:
start switch (可选) case (case1) : 查询; : 输入标题; if (是否查询成功?) then (是) : 返回查询结果; else (否) end endif case (case2) :修改; case (case3) :删除; case (case4) :添加; endswitch stop
-
循环
1. @startuml start repeat :测试某事; if (发生错误?) then (没有) #palegreen:好的; break endif ->not ok; :弹窗 "文本过长错误"; repeat while (某事发生文本过长错误?) is (是的) not (不是) ->//合并步骤//; :弹窗 "成功!"; stop @enduml 2. @startuml start while (data available?) :read data; :generate diagrams; endwhile stop @enduml
如下图:
@startuml start repeat :测试某事; if (发生错误?) then (没有) #palegreen:好的; break endif ->not ok; :弹窗 "文本过长错误"; repeat while (某事发生文本过长错误?) is (是的) not (不是) ->//合并步骤//; :弹窗 "成功!"; stop @enduml
start while (符合条件?) is (是的) :good; endwhile(否) stop
-
并行处理
@startuml start fork :行为 1; fork again :行为 2; end fork stop @enduml
如下图:
start fork :行为 1; fork again :行为 2; end fork stop
-
泳道
@startuml |Swimlane1| start :foo1; |#AntiqueWhite|Swimlane2| :foo2; :foo3; |Swimlane1| :foo4; |Swimlane2| :foo5; stop @enduml
如下图:
|Swimlane1| start :foo1; |#AntiqueWhite|Swimlane2| :foo2; :foo3; |Swimlane1| :foo4; |Swimlane2| :foo5; stop
-
-
序列图
@startuml skinparam sequenceMessageAlign center // 声明字体:居左、居中和居右 autonumber // 为箭头排序 actor actor as a // 角色 boundary boundary as b // 边界 control control as c // 控制 entity entity as e // 实体 database database as d // 数据库 collections collections as co // 集合 queue queue as q // 队列 a -> b : 边界 note left : 默认按照声明顺序排序 activate b b -> c : 控制 c -> e : 实体 e -> d : 数据库 d -> co : 集合 co -> q : 队列 q --> a : 响应 ||| alt 成功 a -> a : 我指向我自己\n good ||| else 失败 a ->x a : 指向失败 loop 记录失败 a -> b : 开始记录 end end note left : alt 条件判断 @enduml
如下图:
skinparam sequenceMessageAlign center autonumber actor actor as a boundary boundary as b control control as c entity entity as e database database as d collections collections as co queue queue as q a -> b : 边界 note left : 默认按照声明顺序排序 activate b b -> c : 控制 c -> e : 实体 e -> d : 数据库 d -> co : 集合 co -> q : 队列 q --> a : 响应 ||| alt 成功 a -> a : 我指向我自己\n good ||| else 失败 a ->x a : 指向失败 loop 记录失败 a -> b : 开始记录 end end note left : alt 条件判断
-
对象图
Type Symbol description Zero or One |o– 0或1 个 Exactly One ||– 1 个 Zero or Many }o– 0或多个 One or Many }|– 1或多个 “|” 代表: " | "
@startuml title 库表结构 skinparam defaultfontsize 14 map "company_info 企业信息表" as company_info { id => [int8] 主键 thscode => [varchar(32)] 股票代码 company_type => [varchar(32)] 企业类型: zw_company_full_name => [varchar(500)] 公司全称(中) project_type => [int2] 项目类型 1:融资类型 2:投资类型 } map "project 项目表" as project { id => [int8] 主键 project_name => [varchar(64)] 项目名称 project_introduce => [varchar(128)] 项目简介 project_desc => [text] 项目描述 project_status => [int2] 项目状态标记 1:最新项目 0:历史项目 project_type => [int2] 项目类型 1:融资类型 2:投资类型 } map "company_project 企业项目表" as company_project { id => [int8] 主键 project_id => [int8] 项目id 关联 project.id company_id => [int8] 企业id 关联 company_info.id } map "course_company_project 课程企业项目表" as course_company_project { id => [int8] 主键 course_id => [int8] 课程id 关联 class_course.id company_project_id => [int8] 企业项目表id 关联 company_project.id } company_info --> company_project project --> company_project company_project -> course_company_project @enduml
如下图:
@startuml title 库表结构 skinparam defaultfontsize 14 map "company_info 企业信息表" as company_info { id => [int8] 主键 thscode => [varchar(32)] 股票代码 company_type => [varchar(32)] 企业类型: zw_company_full_name => [varchar(500)] 公司全称(中) project_type => [int2] 项目类型 1:融资类型 2:投资类型 } map "project 项目表" as project { id => [int8] 主键 project_name => [varchar(64)] 项目名称 project_introduce => [varchar(128)] 项目简介 project_desc => [text] 项目描述 project_status => [int2] 项目状态标记 1:最新项目 0:历史项目 project_type => [int2] 项目类型 1:融资类型 2:投资类型 } map "company_project 企业项目表" as company_project { id => [int8] 主键 project_id => [int8] 项目id 关联 project.id company_id => [int8] 企业id 关联 company_info.id } map "course_company_project 课程企业项目表" as course_company_project { id => [int8] 主键 course_id => [int8] 课程id 关联 class_course.id company_project_id => [int8] 企业项目表id 关联 company_project.id } company_info --> company_project project --> company_project company_project -> course_company_project @enduml