1.1. 2接口(Interface)
接口就是描述类或构件的一个服务()的操作。
如何理解该描述,就好比我们造房子,我们把门呀,窗呀全造地完美无缺,可惜呀我们使用油灯的时代结束了,我们需要拉电线,怎么拉,没有办法了,随便拉吧?太难看了!
何为接口,就是我们为以后拉电线的一个穿墙套管。
再把例子说下去。
我们给了电线留了穿墙套管,但是我们又使用了电话,网络了,强电和弱电不能共用同一套穿墙套管?怎么办?我们还必须给电话线,网络线留穿墙套管,如此变化是不是设计人员可以在当初预料的到呢?
即使,使用了网络线的穿墙套管,那么前两年使用的是同轴电缆,现在使用的是超五类双绞线,还得换?
是不是如此的接口太难留了?是的。
如何解决,重构(目前企业使用较为多的方法)!
①接口的名称
接口的图形表示:一是带有关键字《interface》的矩形表示,接口支持的操作在操作分栏中(如同类图)。
以图示之:
该接口图的右边是一个构件图,目前我们没有叙述,暂不以文档示之。
二类是以小圆圈,接口的名称位于小圆圈的下方。圆圈符号用实线与支持接口的类或其他元素相连,它还可以连向高层的容器,如包。
圆圈表示法不表示接口支持的操作,其操作由接口的矩形列表表示。虚箭头表示类使用接口中声明的操作,但客户类并不需要接口的所有操作。其虚箭头将接口和使用其操作的类连接起来,箭头指向圆圈。
说明:上图表示的是右边的接口的提供者给左边接口的客户使用的。
同样,接口的名称也有简单名和路径名之分。
②接口的作用
接口用于说明类或构件的某种服务的操作集合,并定义了该服务的实现。
接口用于一组操作名,并说明其特征标记和效用(我解释一下这个词,其实质是问题产生的影响),而不是结构。
接口不为类或构件的操作提供实现。
接口的操作列表可以包括类和构件的预处理的信号。
接口为一组共同实现系统或部分系统的部分行为命名。
接口参与关联,但不能作为关联的出发点。(将在关联中详述)
接口可以泛化元素,子接口继承祖先的全部操作并可以有新的操作,实现则被视为行为继承。(将在泛化中详述)
③接口的理解
接口是一个事物(该事物是类或构件)的内部和外部通讯,从数据的初始化到数据的输入输出的实现,接口在中间其"关卡"作用。一将数据从一端取得发给另一端;一是检验数据的合法性,并监督取什么数据和怎样取数据。
在上面建房子的例子中,我们把房内的线全部布置完毕,此时有两种可能,假如室外有电话线,还有宽带接入线,我们选择:一是选择电话线,采用Modem拨号上网的方式,费用低,带窄;二是电话线和宽带线全部接入房中。
这样,第一种方式我们仅需要提供一种电话线的接入接口,而第二种我们需要提供两种接口,其采用的接入方式也不同,线的类别不同。
好了,接口的定义就明显了,接口的两端事物(类或构件)服务是需要电话线和上网线(内部需要是打电话和上网),接口说明了该服务的集合;接口定义的是线(电话线和上网线)的接入,线的接入正是可以打电话和上网的实现;但该接口不能打电话或上网,它仅仅提供一个上网出口?quot;关卡",该关卡定义两端数据交换的类型和原则。
接口的客户又是怎么回事了,情况如此:假如电话线突然断线了,挂了报修电话,电信局来人修(当然宽带有问题,电信有得来人,我用的是电信的),好了,测试人员带来的测试仪器向接口上一挂,便可以测试线路是否畅通,那么我们给测试挂测试仪器的功能就是接口的客户。当然该客户也可以采用一个构件来描述。
1.1. 3协作(collaboration)
协作描述了在一定的语境中一组对象以及实现某些行为的这些对象间的相互作用。
协作中有在运行时被对象和连接占用的槽(我不知道读者会不会联想到操作系统上有个邮件槽和管道的名词,其意同矣!),协作槽也叫角色,角色描述了协作中对象或连接的目的。
在汉语中,协作一词是大家相互帮助,一起做某件事,但该词是译词。虽然不苟同,但相差无几,看collaboration也是这个意思。
协作是动作过程中产生的一类类元。如果我们没有做什么,我们如何谈其协作,在工作的基础上才有协作的可能。所以该节到协作图一节再来详述。
1.1. 4用例(user case)
这是让我恐慌的一段,因为没有一个系统是孤立而存在的,任何一个有意义的系统都是为我们亲爱的客户而准备。其实我把这个客户扩大化了,我犯"浮夸"之嫌,客户是什么,如果我们做一个自用的测试系统,那么客户是谁?是我们,那是当然的。
在设计系统或使用系统时,都会有人参与其中,参与其中都做些事,那么这些人(actor)和事就是用例。
user case在一些译书,常被译为"用况",况者何意?情况?状况?有人参与的事物我个人认为应该为"案例",我觉得应该为"用例"。
如果我们为农场主定制一套软件,精心设计之处,我们应该明白农场主的需要什么?农场的羊很少,它可能需要一个手持式的计算器就可以完全地解决问题,当然如果该计算器中需要软件的话,我们可以为之编制;但农场主的羊如果很多,他有好几个牧场,每个牧场都有不同先进的管理设备,那么这位农场主可能需要一个设备运行情况的信息采集装置,我们可以为之定做一个信息采集、集中、显示和分析的一套软件;如果该农场主有一批农业学家为之工作,该农业学家们可能需要天气数据、牧场草皮的情况、羊群中大小的情况分布从而分析羊群的成长情况、抗病能力…等等根据不同的情况,我们来分析该"例子",需要考虑各类不同的数据,并针对该类的情况分析该软件的构架。
创建一个例子的用例(图),我们需要知道其主要因素是我们在创建中可以不详述该用户的用例是如何被实现的!就是系统创建的用例是"大概"、"扼要"地描述该"例子"(此时是指被描述的实际情况)。
① 用例的名称
用例(use case)是一组动作序列(包括它的变- - -衍生物)的描述,系统执行该动作序列(关于序列的理解读者可参见第一章)来为参与者产生一个可观测的结果值。
故,用例的名称是动作的序列名称,同其类名,也有简单名和路径名之分。路径名中用例名的前面是包名。如:
PackageName::UsecaseName
用例的图形表示有两种,一种是椭圆内部标上用例名,该名称可以是简单名也可以是路径名。
用例和类、接口一样是有操作和属性的,如果需要表示出用例的操作或属性,我们可以用带有《use case》的矩形框(类元)表示。
② 用例的表示法和关联
一. 用例和参与者的关联
用例因为参与者的存在而被称谓"用"例,参与者(就是人)与用例间的关联表明参与者与系统实例或类元实例之间的通讯。该通讯是要求型的,表明参与者对系统有那些要求,即意味着系统可以为参与者提供那些服务。
用例对该服务的实现,就是对用例的实现。
如右图即为参与者error.cao先生来计算年终羊的数量,从此也可以看出来,error.cao 先生是个农场主,他关心的是年终羊的数量,但此时没有到年终,他只可以预测年终羊的数量,此时他使用了ForecaseAccount的操作方法。
如此,我们即可以了解用例和参与者的关系,在一般情况下,我个人的理解是:参与者就是用例者。
二. 用例和状态机、活动图的关系
我们还没有认识状态机和活动图,故等等再看。
三. 用例扩展点表示法
扩展点是一个用例内部的命名实体。描述了来自其他用例的用例动作序列可以被插的位置。扩展点引用了用例行为顺序中的一个或一组位置,提供扩展和行为顺序文本之间的一个间接级别。对于扩展点的扩展关系可以被独立地改变,如图所示的AccountSheep用例和DatetimePhase用例间的关系是扩展关系,该关系从AccountSheep用例的操作或属性上,并不影响表述(文档化和实现)。
右图是用例的关系图,在AccountSheep的用例的说明下表示有一个扩展点,该扩展点用《extend》来表示该关系,同时该扩展点可以在用例区域里被列举出来,标题为extension points,如DatetimePahse用例。
泛化关系用箭头表示,从子用例到父用例的一条实线,一个实三角箭头(该图采用Rose画的,看上去象个空心的)指向父用例。
先简单说一下泛化,先认识一下"同化"一词,其意为让其与自相同,至少类别是相同的,在图论称是同构的。好,那么泛化呢?即让其拓扑!
使用数学语言很简单就分析,各个术语间的区别和联系,到现在你应该有点知道,我为什么苦口婆心来说明数学的分析的重要性的,别急,后面看到的优点还多呢!
用例被泛化成一个或多个子用例,这些子用例代表父用例更多更明确的形式,但应该注意,这些明确的形式相对父用例来说是有方向性,即说明子用例仅仅在父用例的某部分操作或属性上进行泛化,既是如此一句:同一父例的不同特化是独立的(当然该独立是有方向性的)。
当然,子用例继承了父用例的所有操作和属性。