3.3.1 发现角色
通过回答下列的一些问题可以帮助建模者发现角色
使用系统主要功能的人是谁即主要角色
需要借助于系统完成日常工作的人中谁
谁来维护管理系统次要角色保证系统正常工作
系统控制的硬件设备有哪些
系统需要与哪些其它系统交互其它系统包括计算机系统也包括该系统将要使用的计算机中的其它应用软件其它系统也分成二类一类是启动该系统的系统另一类是该系统要使用的系统
对系统产生的结果感兴趣的人或事是哪些
在寻找系统用户的时候不要把目光只停留在使用计算机的人员身上直接或间接地与系统交互或从系统中获取信息的任何人和任何事都是用户由于这里讨论的用例模型用于模型化一个商务business 活动所以角色通常指的是商务中的顾客但是你要在头脑中保持清醒的认识顾客的含义并不是计算机术语中的用户在完成了角色的识别工作之后建模者就可以建立使用系统或与系统交互的实体entities 了即可以从角色的角度出发考虑角色需要系统完成什么样的功能从而建立角色需要的用例
3.3.2 UML 中的角色
UML 中的角色是具有版类角色的类该类的名字用角色的名字命名用以反映角色的行为角色类包含有属性行为和描述角色的文档性质UML 中用一个小人形图形表示角色类小人的下方书写角色名字如图3-2 所示图3-2 左侧的矩形是具有版类角色的类即角色类的另一种图示方式右侧的标准图示图标一般用在用例图中
保险代理
角色
保_________险代理
图3-2 角色类的图示方法示例
3.3.3 角色之间的关系
由于角色是类所以它拥有与类相同的关系描述关于类中的关系的描述参见4.3 节
在用例图中只用通用化关系描述若干个角色之间的行为通用化关系的含义是把某些角色的共同行为原角色中的部分行为抽取出来表示成通用行为且把它们描述成为超类superclass 这样在定义某一具体的角色时仅仅把具体的角色所特有的那部分行为定义一下就行了具体角色的通用行为则不必重新定义只要继承超类中相应的行为即可角色之间的通用化关系用带空心三角形作为箭头的直线表示箭头端指向超类
图3-3 示例的是保险业务中部分角色之间的关系
其中客户类就是超类它描述了客户的基本行为
比如选择险种由于客户申请保险业务的方式可以不同故又可以把客户具体分为二类
一类是用电话委托方式申请用电话申请客户类表示另一类则是亲自登门办理用个人登记客户类表示显然电话申请客户类与个人登记客户类的基本行为与客户类一致这两个类的差别仅仅在于申请的方式不同于是在定义这两个类的行为时基本行为可以从客户类中继承得到从而不必重复定义与客户类不同的行为则定义在各自的角色类中
3.4 用 例
3.4.1 什么是用例
用例代表的是一个完整的功能UML 中的用例是动作步骤的集合动作action 是系统的一次执行能够给某个角色输出结果值与角色通信或进行计算或在系统内工作都可以称作动作用例应支持多种可能发生的动作比如自动售货系统中当顾客付款之后系统自动送出顾客想要的饮料这是一个动作付款后若需要的饮料无货则提示可否买其它货物或退款等等系统中的每种可执行情况就是一个动作每个动作由许多具体步骤实现
用例具有以下的特征
1 用例总由角色初始化
用例所代表的功能必须由角色激活而后才能执行一般情况下角色可能并没有意识到初始化了一个用例换句话说角色需要系统完成的功能其实都是通过用例具体完成的角色一定会直接或间接地命令系统执行用例
2 用例为角色提供值
用例必须为角色提供实在的值虽然这个值并不总是重要的但是能被角色识别客户
个人登记客户 电话登记客户
图3-3 角色之间的通用化关系示例
3 用例具有完全性
用例是一个完整的描述虽然编程实现时一个用例可以被分解为多个小用例函数每个小用例之间互相调用执行一个小用例可以先执行完毕但是该小用例执行结束并不能说这个用例执行结束也就是说不管用例内部的小用例是如何通信工作的只有最终产生了返回给角色的结果值才能说用例执行完毕用例和角色之间也有连接关系用例和角色之间的关系属于关联association 又称作通信关联communication association 这种关联表明哪种角色能与该用例通信关联关系是双向的一对一关系即角色可以与用例通信用例也可以与角色通信用例的命名方式与角色相似通常用用例实际执行功能的名字命名比如签定保险单修改注册人等用例的名称一般由多个词组成通过词组反映出用例的含义这也符合我们通常习惯的见名知义的约定注意用例表示的也是一个类而不是某个具体的实例用例描述了它代表的功能的各个方面也就是包含了用例执行期间可能发生的种种情况比如多种方案选择错误处理例外处理等用例的实例也是一种动作代表系统的一种实际使用方法这个实例通常又叫做脚本scenario 脚本是系统的一次具体的执行路线比如在自动售货系统中张三投入钱币希望购买矿泉水系统收到消息后将矿泉水送出的过程就是一个脚本又如李四投币买矿泉水但矿泉水卖完了于是系统给出提示信息并把钱退还给李四这个过程也是一个脚本当然还可以提供当需要买的东西缺货时提示客户买其它东西而不立即退钱的脚本
3.4.2 发现用例
实际上从识别角色起发现用例的过程就已经已开始了对于已识别的角色通过询问下列问题就可发现用例
角色需要从系统中获得哪种功能角色需要做什么
角色需要读取产生删除修改或存储系统中的某种信息吗
系统中发生的事件需要通知角色吗或者角色需要通知系统某件事吗这些事件功能能干些什么
如果用系统的新功能处理角色的日常工作是简单化了还是提高了工作效率
还有一些与当前角色可能无关的问题也能帮助建模者发现用例例如
系统需要的输入/输出是什么信息这些输入/输出信息从哪儿来到哪儿去
系统当前的这种实现方法要解决的问题是什么也许是用自动系统代替手工操作
3.4.3 UML 中的用例
UML 中的用例用椭圆形表示用例的名字写在椭圆的内部或下方用例位于系统边界的内部角色与用例之间的关联关系或通信关联关系用一条直线表示如图3-4 所示
角色名称
用例A
用例B
用例C
系统名称
用例名称
通信关联
图3-4 用例图示例
图3-5 给出的是某自动售货系统的用例图
客户
卖饮料
自动售货系统
供货人
收银员
供 货
取货款
图3-5 自动售货系统用例图
3.4.4 用例之间的关系
用例之间有扩展使用组合三种关系扩展和使用是继承关系即通用化关系的另一种体现形式组合则是把相关的用例打成包package 当作一个整体看待
1 扩展关系
一个用例中加入一些新的动作后则构成了另一个用例这两个用例之间的关系就是通用化关系又称扩展关系后者通过继承前者的一些行为得来前者通常称为通用化用例后者常称为扩展用例扩展用例可以根据需要有选择地继承通用化用例的部分行为扩展用例也一定具有完全性由于用例的具体功能通常采用普通的文字描述书写因此从文字中划分哪些行为是从通用化用例中继承而来的哪些行为是在用例中重新定义的作为用例本身的具体行为哪些行为是添加到通用化用例中扩展通用化用例的都比较困难引入扩展用例的好处在于便于处理通用化用例中不易描述的某些具体情况便于扩展系统提高系统性能减少不必要的重复工作用例之间的扩展关系可图示为带版类扩展的通用化关系如图3-6 所示
2 使用关系
一个用例使用另一个用例时这两个用例之间就构成了使用关系一般情况下如果若干个用例的某些行为都是相同的则可以把这些相同的行为提取出来单独作成一个用例这个用例称为抽象用例这样当某个用例使用该抽象用例时就好象这个用例包含了抽象用例的所有行为用例之间的使用关系被图示为带版类使用的通用化关系如图3-7 所示
签定保险单
使用
签定汽车保险合同
使用
签定汽车保险合同
图3-7 使用关系图示
客户
卖饮料
自动售货系统
供货人
收银员
供 货
取货款
打开机器
关闭机器
使用
使用
打开机器
关闭机器
使用
使用
图3-8 自动售货系统用例模型
比如自动售货系统中供货和提取销售款这两个用例的开始动作都是去掉签定保险单扩展签定汽车购买合同
图3-6 扩展关系图示
机器保险并打开它最后的动作一定是关闭机器并加保险于是可以从这两个用例中把开始的动作抽象成打开机器用例把最后的动作抽象成关闭机器用例那么供货和提取销售款用例在执行时一定要使用上述的两个抽象用例它们之间便构成了使用