uml学习
1 UML核心元素
1.1 版型(stereotype)
也称“类型”,“构造型”。是对UML元素基础定义的扩展,在同一个元素基础定义的基础上赋予特别的含义,使得这个元素适用于特定的场合。是一种扩展手段。
1.2 参与者(actor)
actor是在系统之外与系统交互的某人或某事物,边界之内的所有人和事物都不是参与者。
谁是actor?
用例一定存在actor,可能是一个人,可能是定时器,也可能是一个消息。actor一定是直接并且主动的向系统发出动作并获得反馈的,否则就不是actor。如下几个例子:
机票购买者通过登陆网站购买机票,机票购买者就是actor
机票购买者通过呼叫中心,由人工座席操作定票系统购买机票,人工座席就是actor
机票购买这通过呼叫中心的自动语音预定机票,呼叫中心就是actor
如果让呼叫中心成为订票系统的一个子系统,并且机票购买者可以自主通过人工座席,自动语音,登陆网站预定机票,则机票购买者就是actor,人工座席是业务工人。
业务主角(business actor)
业务主角是与业务系统有着交互的人和事务,他们用来确定业务范围。业务主角是参与者的一个版型。业务主角是针对业务人员而非计算机。
业务工人(business worker)
记住参与者是在业务系统外的,所以业务系统中的人,就不是参与者。他是主动向系统发出动作的吗?他有完整的业务目标吗?系统是为他服务的吗?
1.3 用例(usecase)
用例的特征
- 用例是相对独立的
- 用例的执行结果对参与者来说是可观测的和有意义的
- 事物应该由参与者发起,不存在没有参与者的用例,用例不应该自动启动,也不应该启动另外一个用例
- 用例必然使用动宾短语的形式出现
- 一个用例就是一个需求单元,分析单元,设计单元,开发单元,测试单元,甚至部署单元
用例的粒度
用例的粒度以每个用例能够描述一个完整的事件流为宜,即一个用例描述一项完整业务中的一个步骤。同一个需求阶段,所有的用例粒度都是一个量级的。
使用plantUML写用例
actor定义角色,或者:xxx: as yyy 定义角色以及别名
usecase定义用例
可以用-->进行关联,:增加描述
@startuml
usecase 购买机票 as "购买机票\n这里可以添加注释,还可以分行
--
分行
===
再分行"
:机票购买人: as user1
actor 人工座席
user1 -> (购买机票) :网站,自动语音
人工座席 -> (购买机票) : 内部系统
@enduml
结果:
1.4 业务实体
业务实体代表业务角色执行业务用例时所处理或使用的事物。业务实体是参与者在完成其业务目标的过程中使用到的或创建出来的,业务实体必须至少被一个业务场景用例使用或者创建,业务实体是类的一个版型,具有对象的所有性质,包括属性和方法,且只应当包含它本身固有的特性。
1.5 包
主要作用是容纳并为其他元素分类,可以容纳任何UML元素。
分包的原则
- 高内聚:分入同一个包中的元素互相联系紧密,具有某些相同的性质,使得包可以抽象出一些接口来代表包内事物与包外事物的交互。
- 松耦合:修改包中的任何一个元素,包中的其他元素不受影响。
- 依赖关系不传递:如果难以做到完全解除依赖关系,至少应当保证包之间的依赖关系不被传递。
- 避免双向依赖或者循环依赖,依赖关系应该是单向的。
几种类型的包
- 领域包:用于分类业务领域内的业务单元,每个包代表业务的一个领域。
- 之系统:用于分类系统内的逻辑对象,并形成之系统。
- 组织结构:用于分类业务领域中的组织结构,可以直接表述企业的组织结构。
- 层:分类软件中的层次,可以描述软件的架构信息。
1.6 分析类
边界类
边界类的场景:
- 参与者与用例之间
- 用例与用例之间如果存在交互
- 如果用例与系统边界之外的非人对象有交互
- 在相关的业务对象有明显的独立性要求,即它们可能在各自的领域类发展变化,但又希望互不影响
一个好的边界类的特点:
- 边界类应该有助于提高系统的可用性
- 边界类应该尽可能地保持在较高的层次(如概念层次)上
- 边界类应该合理封装介于系统与主角之间的交互
- 如果主角改变他们为系统提供输入的方式,边界类就应该是唯一需求改变的对象
- 如果系统改变为主角提供输出的方式,边界类就应该是唯一需要改变的对象
- 边界类必须要知道其他对象类型的需求,以便他们能够得以实施,并相对于系统内部元素保持其可用性和有效性
控制类
控制类用于对一个或几个用例所特有的控制行为进行建模。在边界类访问实体类,实体类访问其他实体类时,建议使用控制类。
实体类
实体类用于对必须存储的信息和相关行为建模的类。实体对象用于保存和更新一些现象的有关信息。从架构角度上来说实体类位于数据持久层。
1.7 设计类
设计类是系统实施中一个或多个对象的抽象,设计类所对应的对象取决于实施语言。设计类用于设计模型中,它直接使用与编程语言相同的语言来描述。
plantUML写类
@startuml
'直接可以使用class的定义方式写
class Dummy {
String data
void methods()
}
class Flight {
flightNumber : Integer
departureTime : Date
int fun1()
String fun2()
}
note "这是注释" as N2
Flight .. N2
Dummy <|--- Flight
@enduml
结果:
1.8 关系
关联关系
关联关系用一条直线表示,描述不同对象之间的结构关系。关联关系是描述对象之间静态的,天然的结构。
' A 关联B
@startuml
class A {
}
class B {
}
A -- B
@enduml
依赖关系
依赖关系是用一条带箭头的虚线表示,描述一个对象在运行期会使用到另一个对象的关系。
@startuml
' B 依赖 A
class A {
}
class B {
}
A <.. B
@enduml
扩展关系
扩展关系是用一条带箭头的虚线加版型<< extends >>来表示的。它特别用于在用例模型中说明基本用例中的某个扩展点插入扩展用例。
@startuml
' B 扩展出A
usecase A
usecase B
A <.. B:<<extends>>
@enduml
如打电话时,如果通话过程中收到另一个呼叫,我们可以将当前通话保留而接听另一个通话。在这个场景中,保留通话用例就是打电话用例的一个扩展用例
包含关系
包含关系用一条带箭头的虚线加版型<< include >>表示。它特别用于用例模型,说明在执行基本用例的用例实例过程中插入的行为段。包含用例总是带有抽象性质的,基本用例控制与包含用例的关系,并可依赖于执行包含用例所的结果。包含用例表示的是必需,而不是可选。它应当在概念用例模型中,通过分析业务用例场景而抽象出关键的必选的核心业务而形成包含用例。
@startuml
' A 包含B
usecase A
usecase B
A ..> B:<<include>>
@enduml
实现关系
实现关系用带空心箭头的虚线表示。它特别用于在用例模型中连接用例和用例实现,说明基本用例的一个实现方式。
比如缴纳电话费业务的例子,缴纳电话费是一个业务目标,实现途径可能有营业厅缴费,银行缴费,预存话费等,每个用例实现都是同一个业务目标的不同实现过程。
@startuml
usecase 缴纳电话费
usecase 营业厅缴费
usecase 银行缴费
usecase 预存话费
缴纳电话费 <|.. 营业厅缴费
缴纳电话费 <|.. 银行缴费
缴纳电话费 <|.. 预存话费
@enduml
精化关系
精华关系是用一条带箭头的虚线加版型<< refine >>表示的。它特别用于用例模型,一个基本用例可以分解出许多跟小的关键精化用例,这些更小的精化用例更细致的展示了基本用例的核心业务。精化关系仅仅用于建模阶段。
@startuml
usecase 预存话费
usecase 开立账户
usecase 存入现金
usecase 转账
usecase 支付划帐
预存话费 <.. 开立账户:<<refine>>
预存话费 <.. 存入现金:<<refine>>
预存话费 <.. 转账:<<refine>>
预存话费 <.. 支付划帐:<<refine>>
@enduml
范化关系
范化关系是一条带空心箭头的直线表示。说明两个对象之间的继承关系。不建议在用例之间使用范化关系。
@startuml
' A 继承自B
class A {
}
class B {
}
A --|> B
@enduml
聚合关系
聚合关系是用一条带空心菱形箭头的直线表示的。聚合关系用于类图,特别用于表示实体对象之间的关系,表达整体由部分构成的语义。整体和部分不是强依赖的,即使整体不存在了,部分依然可以存在。
@startuml
' A聚合到B上,或者说B由A组成
class A {
}
class B {
}
A --o B
@enduml
组合关系
组合关系用一条带实心菱形箭头的直线表示。组合关系用于类图,特别用于表示实体对象关系,表达整体拥有部分的语义。比如母公司拥有许多子公司。组合关系是一种强依赖的特殊聚合关系。如母公司解体了,子公司也将不存在了。
@startuml
' A组合成B, B由A构成
class A {
}
class B {
}
A --* B
@enduml