下面呢我们这个结合前面的一些内容 我们看一个思考题,就是个实际的一个建模的一个过程,这是一个
很简单的一个,小的一个练习,就是一个
医疗信息管理系统中的一个住院管理 系统,这里边呢涉及到这个医生和护士
这个使用者,这个有医生呢登录系统后呢可以
查看特定住院病人这个监测记录,然后可以开写处方,填写这个
一些处方的一些数据项 然后呢,这时候医生就可以把这个处方交给护士,然后护士呢
根据医生的这个医嘱然后呢再
这个根据处方定义的这个时间间隔内,时间跨度内
定期、 定量的给这个病人服药或者注射等等
另外呢,根据医生的要求可以给这个病人呢进行一些
查看,就是进行一些这个一些指标的一些测量,也是定期、 定量
这个测量,这些指标,血压这个什么监控,根据他这个 病人这个病情,以及医生的一些指令进行
根据护理的一些常规规定,然后 测量一些,这些指标,并且把它们记录到系统
这个病人本身不使用系统,但是呢病人的信息放在系统中 病人是什么名儿啊,这个基本信息啊
所属科室啊,什么病啊,护理等级等等 这是要放到我们的系统中,并且这儿有个报警器
病人随时可以按报警器,报警器一旦响了之后呢就必须要
通知护士来,护士如果这个,报警器响了不来,出现漏接
这回要追究值班护士的责任,这就大概是这么一个系统 这个系统呢我们可以综合运用我们前面讲的
类图和use case图来做一个类图,首先呢这个我们
根据这个需求分析我们做一个类图,做一个use case图,use
case图包括这个医生和护士 还有这个报警器,这里为什么不选病人呢,就是因为这是我们
前面讲的use case这个原则,就是因为我们当前这个系统啊
实际上需要直接跟报警器打交道,而这个报警器 跟病人之间,它是这个病人按报警器,报警器
再通过向我们系统传递一个信号 这个报警器不同于键盘、 鼠标,它不是一种通用的一个
硬件设备,是个专用的这个设备,需要我们在 编写这个当前的系统中啊,我们单独地开发
报警器的接口,这样的话呢我们没有一些可以依赖的一些
操作系统或者说是什么编程序,编程语言的一些 这个便利条件可以依赖,使得我们这个
把这个报警器变成透明,看不到报警器我们就不使报警器 直接看到用户了,但现在报警器对我们不透明,所以我们只能看到
报警器,因此用户,这个病人就不能作为参与者了。
其他的一些问题呢我们就 这个很简单,是吧,就是他们都可以登录,用户和医生和病人
这个病人呢可以进行登录,医生呢是查看病人的监测性记录,并且开一些处方
护士呢浏览这个治疗指令,浏览一些监控指令
然后护士和报警器之间,和系统之间,三方进行报警,因为他们为什么 是一个三,两个参与者用一个use
case,那是他们是一个实时性很强的一种交互 序列,涉及到三方同时的一个互动,大概是这种情况
这个是一个非常简单的use case,下面我们根据use case之后,我们建立一个类图
这个类图是怎么考虑的,这些所有的画粗体的都是一个主动类,它们
可以不经过这个接受其他的消息,就可以向其他对象发送消息 医生、 护士和病人
为什么这里又把病人拿进来呢?就是因为这时候我们需要管理病人信息 所以把病人作为一个参与者,但是为什么这时候这个病人作为
这个主动类呢,就是因为这样比较符合 这个现实世界的一个实际的情况,就是我们这时候呢
这个由于病人,为了管理病人的信息 把病人拿过来,但是呢又为了非常好的模拟这个病人
按报警器的这么一个情况,所以我们把病人作为主动 类,而不把报警器作为主动类了。
这是从系统边界这个角度来识别 这些对象。
另外呢我们可以从问题域,问题域就是当前医生,医院这个问题域中有哪些类呢?
看得见的,摸得着的,这是一些处方 这个医生、
病人、 护士,这些都是可以的 还有一些是一些事件,就是监测活动
治疗指令、 监测记录、 报警记录等等,这些呢需要
做一些,一些这个适当的深入的调查才可以 然后识别一些
这个属性,一方面是借助于常识,另一方面借助于 问题域,还有就是细心观察,就是相当于我们这个住院的时候
经常看到有的病人这个床上有一些小的标志,不同的一些小三角,那标示病人的护理等级
是吧,这个实际上要填入病人的这个信号,你如果不 敏感观察到这些信息呢,无法识别出这些属性来。
这个,再就是 本地中那个并没有一些真正的纯粹的系统责任方面一类的,使得我们这个
识别起来比较简单,因为这个,所有的这些功能基本上通过
系统边界方法和这个问题域方法,基本上都能识别出来 所以这个就不需要那个
凭空的我们发明一些新的一些类,现实世界中不存在的一些类 来这个承担某些系统责任,系统责任全部都由这些
现实世界中存在的一些类来这个承担了,所以没必要 再重新识别。
所以对于识别关联关系的时候,我们注意 就是说在医生和处方类之间,它们为什么具有这种关联关系呢?
那就是我们要考察关联关系的两个条件,必须具备其一
就可以,就医生和处方之间为什么要有这个关联关系?第一,医生
需要在开写处方的时候需要调用方法 调用处方这个类中的编辑方法,修改方法等等,因此这是满足条件一
第二个呢,医生和处方之间要记录,要有一个 永久性的存储这个信息,以便于
出现一些事故,需要追究责任的时候要追查到 医生的这个责任,因此
从两个角度它都有,所以呢这个肯定这个关联是可以需要的,只要有一个就可以了,它是- 具有两个
所以,另外呢就是说这个护士和报警器之间需不需要这个关联关系
这个可能一开始分析,很多同学都想当然地 认为这个应该是有这个关联关系,按照现实世界中这个
记录哪个报警器这个 和这个护士发生了关系,或者说护士呢
是这个报警器向护士发送了一个信号,然后让护士
调用了护士的服务 但实际上我们仔细分析一看,发现什么问题呢?就是说
它两个条件都不满足,第二个条件就是说这个报警器
调用护士,报警器向护士发送消息
这个要调用护士服务这种方式,不是通过软件从而来实现的 报警器通过这个报警响
是变成声波的,把计算机的信息变成声波的 以一种非软件的方式传递的这个消息,因此呢这个条件不成立
所以呢,这个这个护士和这个 这个报警器之间调用服务这个信息是没有的
这个,第二个信息呢就是这个监测 这个护士和病人如果说存在一个
一个这个 互动,是吧,如果说是当我们这个表示哪个护士对哪个报警器负责
其实这种这个永久性的存储,这个 监控,或者说是永久性的存储这种
护士和报警器的这种信息呢 确实是我们系统责任的一个方面,但是呢
它可以通过报警记录在这儿来完成,这时候我们这个
一个报警器通过一个报警记录来在这儿记录
这个报警器和哪个护士发生了关联,这个护士是不是 这个接,接到了这个当前的这个
情况,也就是说它是通过报警器 报警记录,然后呢还通过这个护士,这
三,两个关联关系来记录这个信号,因此也不需要 这个直接,它们之间直接建立这个直接的关系。
所以其他的我们就不说了,这个就是我们简单的看一下我们如何应用我们这个课程中的一些
简单策略来识别出一些类图,当然这个可以
至于这个处方,是吧,这个还可以进一步地这个进行优化,
监测哪些指标是不是又用到了设计模式, 当然这里边我们没有给出设计模式,
其实这个监测活动还可以对应一些监测的一些指标项, 这样的话是使得我们这个系统更加完善,还可以进一步优化。
因此我们可以看出,这个分析模式,刚才我们讲的分析模式,是非常有用的, 这个这是这个这个例子。
好,下面我们这个再讲这个包图,
这个就是说在对于一些复杂的情况下,我们这个如果说系统
有几十个类,上百个类的时候,不可能放在一个图,那就没法看了,这时候我们要把
这些几十个类上百个类,把它们组装到一个包里边去,一个或几个包里边去, 这就是有必要建立包图。
所以对于非常大的工程量的分析和设计来说,包图是非常有必要的,
那么什么是包呢?包就是控制,进行对模型元素分组的这种机制。
当然这个包啊,里面不一定非得装类,有些时候还可以装接口, 对于我们后面讲的一些构件和节点,也是可以装到包里边去的。
但是,还可以装 usecase,但是呢它不能装什么呢?这个比如说我们讲
那些行为,是吧这个状态,是不需要装的,
然后这个一些,一些交互,它们 也没必要装到包里边去,因为这些图里边内带了一些
类似于这种包的一种机制,可以实现这种 更大粒度的,将一些小的一些元素组合成更大粒度的一种
机制,不用这个包这种方式,这个我们后面会提到。
因此呢这个
如何把它们分到一个包里边去呢?这个就是一个一定要实现一种松耦合,高内聚,
就是放到一个包里边的这些类,或者这些 classifer,它们应该是高内聚的,
它们的关系应该非常,非常多,但是包和包之间的这个,
类之间的这个关联应该尽可能少,但是不可能没有,如果没有的话那就成了离散的若干个子- 系统了。
但实际上它们不可能,就是包和包之间的这个类之间还是存在一些
松散的一些关系的,那么这些松散的关系是如何进行建立呢?
那是不是直接跨越包的边界,画上一个关联关系就构成了泛化关系,不是的,那样的话使得- 我们这个
看起来也不美观,也无法实现一个非常好的一种分离。
解决这个问题呢, 实际上呢我们可以这个
应用什么呢?应用后面我们讲的几种关系,三种关系
来进行描述,那么这个包的目的呢就是 要这个一方面呢就是为管理复杂性,
是把一个很大的一个模型拆分成若干个小的,可以阅读的 模型,另外定义这个
namespace,名域,然后使得我这个 在包里边,不可能有重名的类,但是呢
不同包之间可以重名的类,它们代表不同的类,为什么呢?因为它们 是借助于包名加类名的方式来唯一的定义它们的
确定它们的这个,是否是这个完整的名字,这种方式来确定。
并且包可以用于不同的目的,这个核心
概念呢就是主要的概念一个是包,一个是包之间的关系, 包的关系有三种,一种是引入,一种是访问。
什么是引入呢?就是 import, 那就是说包和包之间呢,如果一个包需要与
一个包的类需要与另外一个包的类建立一种
关系,比如说泛化关系,关联关系,那这时候呢我们就将这两个类之间建立一种
引入关系,这时候呢就把另外的一个类中的需要
建立,另外一个包里边的需要建立这个引入关系的那个类
把它引入到我们这个包里边,然后跟它建立关系,通过这种方式
可以使得我们在一个包里边,既能看到本包里边的各种
类之间的关系,又能看到这个包里边元素的,包里边的这个类 和其他元素之间有什么关系。
并且它是分离的,是吧,我们把它引入过来之后呢, 这是相当于从别的包里边借来一个元素,然后与它建立关系,但实际上呢,它
产生的作用是,是跨越包之间建立元素之间的
各种各样的关系,这叫引入关系,import 这种关系。
这个还有一种关系叫访问,访问是一种受限的一种 这个引入关系。
它们的区别在哪?就是引入,新引入的这个 包中的这个元素可以完全虚拟的把它作为我自己的这个元素使用,
我可以给它改一个名,我可以给它
把它可见性改了,甚至是呢,这个如果说是 我
A 这个包引入了 B 包中一个类,
但是这个 C 的这个包呢又引入 A 中的类,
它可以传递,是吧,它可以,引入的这些元素可以在包之间传递。
但访问关系不行,访问的话, 如果包和包之间是一种
access 关系,那么它可以 在这种访问关系下,我可以引入它的一个元素,但是呢
这个元素到我这呢是一种这个可见性为 这个私有的这么一种元素,不可能再被其他的元素
其他的包里边的再访问这个元素,所以它们之间的区别就在这。
这个此外呢我们可以定义这个包
内的可见性,也就是说包内的一些元素对包外之间有什么可见性,公有的,受保护的,私有的- ,和包内的, 这跟类类似,这是可见性。
包和包之间也可以继承,也可以继承关系,就是它们之间呢, 这个两个包之间继承,那就是说它一个
如果 A 包继承,或者说和包 B 构成泛化关系,那么它们实际上呢就是把包中的所有的
这个元素,和这个不管是公有的和受保护的全部都给拿过来了,
也是一种这个实现包和包之间的一种这个元素之间的关系的一种 大粒度的一种关系。
那么什么时候使用包呢?无外乎 两种方式,自顶向上,自顶向下和自底向上。
有些情况下我们首先要通过自顶向下,就是首先建立一个大的系统,
首先呢先不建立一些小的一些类,而是呢把这个大系统分为若干个小的子系统,
子系统再分为更小的一些什么模块,模块到模块然后呢再建立类, 这种方式。
再就是自底向上,已经建立好了 一个非常庞大的一个类图,然后呢我现在为了便于交流,便于让大家
加深了解,我把它打散成,把这一百多个,比如说一百多个建模元素给它打散之后变成
把它们放到十个包里边去,每个包里边也就是不到十个类,然后这样的话便于 给其他人进行交流,这样组织庞大元素。
另外呢就是包和包之间呢,包内的一些元素是比较相关的,
相关的一些建模元素组织成包,再就是避免 这个重名,包内不允许重名,包之间的元素是可以重名的。
因为我们开发很大的系统,难保不齐这几百个类中有一个重名的,
这个我们重名的时候通过包名加类名,这种方式来 唯一的定义这个类。
如何划分包呢?这个 无非就是这个,实际上划分包的这个原则是非常灵活的,
甚至要比识别类要灵活的多。
一般来说呢这个,我们这个一定是 把一些结构上
非常紧密的一些类 的集合把它们识别到一个包里边去,这些识别的时候呢,
可能根据泛化结构,根据关联密集的一些类, 这个把它们识别为一个包,其他稍微松散的一些,比较
松散的一个关系的类,分配到另外一个包里边去,它这个 依据呢也有很多,这个根据,实际上根据
实际的问题可以进行灵活的调整,这个是包的问题。
这个关于这个识别划分包呢,实际上这个
其他的一些问题呢,大家可以参考我们教材上的一些 原则。
好,这样这个,但是我们这些 例题呢,关于包的这些例子呢,我们可以到后续的一些案例中可以
体会到,特别是在设计中,我们会 经常会用到这个包,包和包之间 import 的关系。
那这个本周呢我们就这个 这个类的这个部分我们就介绍到这。