12接口类型角色.docx
《12接口类型角色.docx》由会员分享,可在线阅读,更多相关《12接口类型角色.docx(30页珍藏版)》请在冰豆网上搜索。
12接口类型角色
第十二章接口、类型、角色
1、引言
●以部件化的形式来建造或生产产品是某一工业领域成熟化的标志。
●例如,人们居住的房子包括
●建筑结构
●电气系统
●供水系统
●
排水系统
●供暖系统…
●这些系统的的互相配合经过精心设计
●当人们希望修改电器系统的走线时,
●不会要求将建筑的总体结构推翻重建。
●当人们在对房子进行装修时,
●也不会将电气系统破坏。
●之所以能够做到这一点,是因为
●在设计房子时,考虑到了房屋不同组成部分之间的耦合关系,使得对其中一部分的局部更改不会影响另一部分的整体运行。
●对于软件系统的设计和建造而言,也存在着这样的要求。
●软件系统的内部是由大量的互相关联的类构成的。
●当对其中的某一类的局部进行修改的时候,
●不能使得其它的类不能工作。
●软件系统中的类依据其所起的作用的不同,
●有可能形成若干由耦合紧密的类构成的子集,
●
而子集之间的耦合则比较松散
●(在UML中,这样的子集可以用模型包来界定,如需强调其语义上的完整性,可以把它设为子系统变体(〈〈subsystem〉〉))。
●这时,对子集内部的类的修改,甚至对子集本身的内部构成的修改,都不应导致其它子集或其它的的类不能正常工作。
●为了达到这一点,可以为类或类的集合设定一个外部的行为特性的规范,
●只要对类或类的集合的修改不改变这个行为规范,
●就可以保证其它的类乃至整个系统能正常工作。
●这样的规范,在UML里被称为
●接口(interface)。
●接口还可以为部件指定外部行为特征,从而能够实现软件系统的部件化,这意味这遵循同一个接口的部件可以互相替换。
2、接口
(1)、定义
●在UML里,接口是一系列操作的集合,它指定了一个类或者一个部件所能提供的服务。
●接口是类的变体。
●根据定义,
●只能拥有操作,
●不能拥有属性。
●因此通过接口连接的类或部件之间的耦合是松散耦合。
(2)、接口的图形化表示
●接口是类的变体,
●它的变体关键字是<>,
●
在模型图上
●可以使用变体的记名形式
●(图12.1(a))。
●也可以使用变体的图标形式
●(图12.1(b))。
●变体的记名形式使用了类的标准图符
●所不同的是在此图符的类名的上面加注了用双尖括号括起来的变体的名字。
●对接口而言,变体的名字是interface,
●记为<>。
●由于接口的记名变体表示形式使用了类的标准图符,
●所以可以在此图符的操作分隔区内列出接口的操作的定义。
●由于接口不得拥有属性,所以接口的记名变体形式的属性分隔区必须为空。
●接口的图标形式是一个
●空心圆圈,
●在圆圈下面是接口的名字。
●在用接口的图标形式表示接口时,
●接口的操作不被列出。
(3)、接口的名字
●每个接口必须被指定一个名字,
●用以区分不同的接口。
●
接口是类的变体,
●因此接口的名字就是类的名字。
●在接口的图形表示上,
●接口名字出现在类的名字应该出现的位置。
●接口的名字是一个字符串。
●这字符串称为接口的
●简单名字。
●和类的名字一样,
●在表示接口的简单名字的前面还可以缀以此接口所在的模型包的名字。
●模型包名和简单名字之间用两个冒号分隔。
●这样的名字称为
●路径名字(pathname)。
(4)、接口的操作
●接口强调的是类或部件对外部提供的服务。
●这些服务用一系列的操作表示。
●接口在建模中起着为软件的子系统定义接缝的作用。
●通过接口,使得软件系统中
●内聚性高,
●对外耦合度低的
●类的集合构成一个相对封闭的子系统或部件,
●这子系统或部件对外部的服务
●以接口的形式被规定。
●在建模时,通过接口,可以
●概括地了解类或部件的外部特性,
●而不必关心它们的内部实现和结构。
●在系统实现时,
●可以通过接口的定义实现功能部件的替换或扩充。
●由于被接口描述的类或部件对外部必须具有低的耦合度,所以
●不应把类或部件的内部结构
●即属性
●
暴露出来,
●所以,UML规定不得为接口指定属性。
●接口是类的变体,
●所以接口的操作的描述遵循类的操作的描述的规则。
●例如:
●可以为它指定操作署名,
●可以为操作指定约束,
●可以为操作指定并发属性,
●可以为操作指定变体,等等。
●在模型图上绘制接口时,
●如果需要强调接口的操作,
●则可使用接口的记名表示;
●否则,
●可以使用更为简洁和直观的图标表示。
(5)、接口的规格说明
●接口定义了软件系统内的子系统的接缝,
●它由一系列的操作的定义构成。
●通过接口,
●可以使接口的应用设计人员在不必了解接口功能的内部实现细节的情况下就能设计使用此接口提供的服务的交互。
●对接口的操作的描述包括
●操作的语法(通过操作署名表示)
●和操作的语义。
●对于简单的接口,
●只需罗列出接口包括的操作及其署名就可以使得接口的应用设计人员了解接口的用法。
●对于复杂的接口,
●还必须详细表述正常使用接口必须具备的各种条件。
●
例如,典型地,一个复杂的接口可能在能够正常使用之前必须启动正确的初始化序列;某些操作的调用顺序必须符合指定的顺序,等等。
●
在UML里,
●除了使用操作所具备的基本的描述手段(如:
文档(documentation))外,
●还提供了其它的精确描述手段。
●例如,可以为操作指定
●入口条件(pre-condition)和
●出口条件(post-condition)。
●入口条件和出口条件是操作的约束,
●它们是一个条件表达式。
●如果为操作指定了入口条件,就表明此操作在被启动之前,入口条件必须为真。
●如果为操作指定了出口条件,就表明在此操作执行完毕以后,此条件必须为真。
●在ROSE里,操作的入口条件和出口条件是在操作的规格说明对话框里指定的。
●
如果需要指定接口操作的合法调用顺序,则
●可以使用UML的
●状态图和
●交互图。
●由于状态图和交互图描述的是软件系统的动态行为的发生的先后顺序,
●因此恰好可以用来概括而精确地描述接口的使用。
●在UML出现之间,在描述一个软件部件的对外接口的规格和调用规范时,
●经常使用示范程序来表达。
●示范程序是一种较为不清晰和概括性较差的描述方法,
●因此应尽量避免。
3、实现关系
●接口强调的是类或子系统或部件的外部行为规范,
●它不强调此动态行为的实现方法。
●一个接口的动态行为
●可以用一个类来实现,
●也可以用一个部件来实现。
●同时,一个接口可以同时为多个类或部件规定其动态行为,
●这意味着一个接口可以有多种实现方法,
●不同的类或部件,
●只要它们的实现遵循同一个接口,
●就可以在交互中互换。
●在使用UML为软件系统建模的时候,
●如果要描述某个类或某个部件实现了给定的接口,
●可以使用
●
实现关系(realization)。
(1)、定义
●实现关系是两个分类符之间的语义关系,表明其中的一个分类符为另一个分类符规定了应执行的动态行为。
●实现关系可以连接的分类符包括
●接口和类,
●接口和部件,
●以及用例和协同。
●其中,
●接口规定了类或部件的动态行为,
●用例规定了协同的动态行为。
(2)、实现关系的图形化表示
●实现关系的基本的图形表示是一个
●以空心三角形为终点的虚线箭头。
●箭头指向的分类符是接口或用例。
●
●实现关系的图形表示还有一种
●简单形式,
●它只能用于
●接口的图标表示法,
●这时实现关系被绘制为
●一条连接接口和类或部件的实线。
●由于接口的图标形式是一个空心圆圈,
●和实现关系另一端的类或部件有明显区别,
●所以可以很明显地区分出
●
哪个分类符是接口,
●哪个分类符是实现此接口的类或部件(图12.3)。
●实现关系的基本表达形式可以看作是泛化关系和依赖关系的组合。
●泛化关系是带有空心箭头的实线,
●依赖关系是一个虚线箭头,
●因此,
●可以把实现关系的图形表示看成是保留了
●泛化关系的箭头和
●依赖关系的虚线
●而得到的。
●这样的图形组合也反映了实现关系的特性。
●由于接口(或用例)规定了关系的另一端的分类符应具备的动态行为,
●所以从这个意义上看,
●是实现接口(或用例)的分类符继承了接口(或用例)的动态行为,
●因此,可以认为实现关系具有泛化关系的语义,
●所以可以把泛化关系的箭头保留,
●把它指向接口,
●
表明实现分类符将继承接口的动态行为。
●另一方面…
●另一方面…
●由于接口(或用例)规定了实现分类符的动态行为,
●所以也可以认为接口(或用例)的语义实际上决定了实现分类符的语义,
●从这个意义上,又可以认为实现关系具有依赖关系的语义,
●所以可以保留依赖关系里面的虚线。
●
接口定义了类或部件的外部动态特性。
●当需要在模型图上表示
●某个类需要使用通过接口提供的服务时,
●只需使用
●依赖关系
●连接使用接口的类和接口。
●其中,
●依赖关系的箭头指向接口,
●表明接口被将被此类使用
●(图12.3)。
4、类型和角色
●当类处于关联关系中时,
●类向所在的关联关系的对侧的类
●呈现出了具有特定语义的动态行为。
●此动态行为,在UML里,可以用
●角色(role)
●来概括。
●角色的定义
●角色在模型图上用其名字表达,此名字代表了类呈现给关联关系对侧的特定语义及据此定义的一系列动态行为。
●具体地来讲,此动态行为是用角色所属的类的一系列操作实现的。
●如果
●一个类只可能处在一个关联关系中,
●或它在所有的关联关系中的语义是一样的,
●则用角色的名字来代表角色的语义就足够了,
●因为这时类的所有的操作都是用来实现此角色的动态行为的。
●但在许多的情形下,
●一个类不但会处于多个关联关系中,
●而且存在于多个关联关系中,
●在于多个关联关系中,
●此类所扮演的角色是不一样的。
●例如,Persons是一个类,代表一个人。
●那么,
●如果此类处于和公司(Company)的雇用关联关系中,
●则类Person的角色是雇员(Employee)。
●如果类Person处于和商店(Shop)的关联关系之中,
●则此类的角色可能是顾客(Customer)。
●
对于类Person而言,
●扮演雇员和扮演顾客这两个角色时
●所具备的动态行为是不同的,
●它们分别对应同一个类的
●两组不同的操作。
●这时,如果只用角色名字区别角色的语义,
●就无法精确表达角色的动态行为。
●这时,按照第十一章的介绍,可以用
●接口标识符来
●精确表达类在特定角色中具有的动态行为(图12.4)。
●
类型
●
根据本章介绍的接口的定义,
●接口是用来描述子系统之间的接缝的,
●它代表了一种松散的耦合,
●因此在接口中不得指定属性。
●但是在关联关系中,接口标识符是
●用来定义角色的语义的,
●角色所在的类和对侧的类的耦合
●未必必须是松散耦合,
●因此,
●有时有必要通过关联关系访问另一个角色的类的内部属性。
●在这时,就应该
●通过接口标识符精确描述此角色在关联关系中呈现给对方的类的属性。
●为了实现这一点,UML规定在接口标识符的位置上,不但可以指定接口名字,还可以指定类型(type)的名字。
●
类型的定义
●
在UML中,类型(type)是类的一种变体,它描述了一类对象及这类对象所提供的操作(而不是方法(method))。
●从类型的定义可以看出,
●首先,类型强调的是它代表的类对外提供的动态行为,
●它不为这些动态行为指定方法;
●其次,在类型里可以指定属性。
●在常用的程序设计语言(如C++)里
●预定义的数据类型
●和自定义类型(如C++里通过typedef定义的类型)
●都可以用类型建模。
●从类型和接口的定义可以看出,
●类型和接口的语义之间只有微妙的区别,
●在大多数的情况下,可以互换使用。
●一般来说,
●当需要强调类或部件之间的接缝时,
●使用接口;
●当需要强调类在交互中扮演的角色时,
●使用类型。
●而且在接口中不能定义属性,
●而在类型中可以指定属性。
●一个类在不同的关联关系中可以扮演不同的角色,
●这些角色在语义上的不同
●可以用
●不同的类型
●来精确表述。
●因此,
●一个类能以不同的类型在不同的关联关系中扮演角色,
●或者说,
●此类输出了多个类型。
●如果一个类输出类多个类型,
●在类图上,
●可以通过泛化关系来刻划。
●如图12.5所示,
●一个人在不同的关联关系中可能扮演不同的角色,
●例如:
在公司,它可能是雇员,在商店,他可能是顾客,而在家里,他可能是家长。
●这意味着一个人的动态行为是从雇员,顾客,家长分别继承下来的,所以,
●可以从类Person分别向它输出的类型绘制一个关联关系。
5、建模指南
●接口和类型都是用来规定分类符的外部动态特性的。
●它们在语义上的差别很微妙,
●但在用途上有所差别。
●接口用来描述分类符之间的接缝。
●它可以描述类或部件向外部提供的服务。
●当它为类描述接口时,
●实际上是为一个子系统指定了外部特性。
●在考虑此子系统参与的交互的动态行为和静态结构时,
●可以忽略此子系统的内部实现机制和和结构,
●而把重点放在子系统提供的服务上。
●当接口用来为部件规定其所提供的服务时,
●它为被建造的软件系统提供了
●基于部件的可扩展性。
●遵循同一个接口标准的部件可以互相替换。
●当使用接口为软件系统建模时,
●可以用实现关系
●为接口指定其实现部件部件或类。
●如果要表达某个类将使用接口规定的服务,
●
则使用依赖关系。
●在描述接口的语义时,
●应注意提供完备的文档,
●为了实现精确的描述,
●可通过
●交互图
●和状态图
●描述接口的调用规范。
●可以使用
●入口条件和
●出口条件
●为单个的操作指定其
●在调用之前
●和调用之后
●系统必须满足的条件。
●
和接口不同,
●类型
●描述类在交互中通过角色呈现给关联对侧的类的动态行为。
●类型表达的类和类之间的的耦合不必须是松散的,
●所以在类型中可以指定属性。
●当一个类参与多个关联关系时,
●它可能会扮演不同的角色,
●使用类型可以只把和特定关联相关的类的操作和属性暴露出来。
●类型的这种功能,
●在分析源代码时十分有用,
●例如,
●在分析一个复杂的类的一个复杂的操作时,
●可以通过类型把和此操作相关的属性和其它操作暴露出来,
●而屏蔽掉其它无关的类的成员,从而有助于对此操作的实现原理的分析,描述和存档。
●
如果
●一个类参与了多个关联,
●并在其中扮演了多个不同的角色,
●而且此类在交互的过程中其角色是动态地转换的,
●那么,
●这种角色的动态转换也可以在
●交互图上
●用类型的变换表现。
●例如,图12.6,
●一个人(Person)的对象p
●在被录用(hire)之前的类型是
●职位候选人(candidate),
●而在被录用之后,
●自动变为雇员(Employee)。
●在这里对象类型的转换用
●消息的变体
●<>
●表示,
●在对象名字的下方是
●用方括号扩起来的类型的名字。