您好,欢迎访问三七文档
第12章约束到目前为止,本书中介绍的许多表示法都是图形的。这些图标表示了许多概念,同时通过按一定方式连接这些图标,还表达了许多系统特性。例如,连接两个矩形的线表示了两个类之间的关联,并说明了这些类的实例如何互相链接。图中的文字用来命名和标注模型元素,添加特定的注文,例如,重数或监护条件。图形表示法适合于展示系统的结构方面,但对于描述模型元素的细节特性,或者由相关业务规则对这些模型元素所附加的限制方面,并不是很有效。这些附加特性可以用约束的形式添加到模型中。一个约束是关于一个或多个模型元素的断言,它指明了该系统处于合法状态时,系统必须满足的特性。例如,假定一个银行开设了一种具有优惠利率的新型储蓄账户,但要求该账户的余额必须保持在0到250,000镑范围内。如果存款(deposit)或取款(withdraw)导致余额(balance)超出此范围则会被拒绝。图12.1表示了这种储蓄账户类(SavingAcount),在注解内非形式写出的是对它的约束。图12.1受约束的储蓄账户UML中非形式写出的约束应当用花括号‘{}’括起来,放在所描述的模型元素的内部或紧靠所描述的元素的地方。也可以放在注解的图标内,并用虚线连接到所描述的模型元素。约束指明的特性可以是真或假。例如,给定图12.1中储蓄账户类的任一实例,约束的真假值将取决于该实例的余额值是否在所述余额范围内。系统必须确保所有约束为真。例如,如果一个账户的余额小于零,就会指出一个错误已经发生,系统已处于非法状态。UML对于少量常见的情况定义了标准约束。更一般的约束可以用非形式化的英语、更规范的约束语言或者目标程序设计语言的表示法写出。UML定义了一种约束语言,称为对象约束语言或简称为OCL。本章将描述OCL最重要的特征,并给出使用OCL的例子。12.1标准约束UML规约定义了若干标准约束,用于不同的模型元素。例如,在交互图中的链接和实例,或者对应的角色,可以如图9.10和9.12中那样,说明为‘new’,‘transient’或‘destroyed’,以指明它们在一个具体交互中的生命期。这些约束与常见的有点不同的是,它们是以描述了被约束元素的一般特性的面目出现的,而不是陈述了一个系统状态可能是真或假的断言。更符合习惯的是对关联定义的标准约束。12.1.1‘xor’约束‘xor’约束可以应用到两个或多个关联。当一个类参与多个受约束的关联时,‘xor’约束是很用的。xor约束用于指明在任一给定时刻,该公共类只能参与一个受约束的关联。图12.2表示的是用‘xor’约束指明,银行客户(customer)在同一时刻不能同时开有储蓄账户(savingaccount)和存款账户(depositaccount)。注意,受该约束限制的关联必须包括重数为0的情况。图12.2xor约束12.1.2子集约束关联的子集约束在UML规范中和其它地方只是作为例子说明的,而不是正式地作为标准约束定义的。这种约束可以用在连接相同两个类的一对关联上,它说明作为一个关联的实例的链接集合,必须是另一个关联的实例的链接集合的子集。图12.3子集约束子集约束可以用一个附有此约束的依赖箭头,将这些关联连接起来表示。该依赖箭头尾部所连接的关联的实例集,必须是该依赖箭头所指向的关联的实例集的子集。图12.3表示的是使用子集约束的一个例子,此例子引自UML规范。它表示了两个关联,分别说明谁是委员会(committee)的成员(member)和主席(chair)。如果没有这个约束,这个图说明某个人可能是委员会的主席同时却不是该委员会的成员。子集约束通过断言:chair关联链接的任何一对对象也必须由MemberOf关联链接,排除了这种可能。12.2对象约束语言标准约束是很有用的,然而要一般地应对各种约束,还需要更灵活的手段。例如,考虑图12.4所示的对象图,它表示了在银行应用中不多见的情况。这里一位借记卡(debitcard)的持有者与该卡所属账户的持有者不是同一个人。我们希望对这个模型定义一个约束排除这种情况,这种约束用前面定义的约束是做不到的。非形式地说,为了排除这种情况需要附加的约束是,所有借记卡的持有者必须是该借记卡所属账户(account)的持有者。在某些情况下,非形式的约束完全能胜任,但要用英语清楚地、无二义性地指明一个复杂条件常常非常困难,即使在相对简单的情况下,说明约束的语句也会有些费解,在初次阅读时其意思也不一定显而易见。为了解决这些问题,计算机科学家已经开发了各种各样的形式规范语言。由于使用了数学符号,这些语言显得有些难以接受。OCL对象约束语言试图提供一种可用的、基于文本形式的规范语言,用来书写用于UML模型的约束。图12.4不常见的情况在上述例子中,所要求的约束可以作为具有下述特性的借记卡来指明。设想有一个借记卡实例,它直接链接到持有该卡的客户,但也间接地链接到另一位客户实例。沿着连接该借记卡到所属账户的链接可以检索到该账户,然后可以检索到持有该卡的第二位持有者。一旦检索到这两个客户对象,我们就可以很容易地简单、明确地指明约束的内容:在这两种情况下,到达的必须是同一个客户对象。这个例子使我们想到,像OCL这样的约束语言,应当提供三种必不可少的能力:1.能够说明什么模型元素被约束。被约束的元素称为约束的语境,在12.3节讨论。2.能够通过模型导航,确定与所定义的约束相关的其他对象。借助于在12.4节讨论的导航表达式可以做到。3.能够对语境对象和借助于导航表达式检出的对象做出断言。这些断言类似于程序设计语言中使用的布尔表达式,但如12.6节所讨论的,断言具有更强的表达力。12.3约束的语境每个OCL约束都有一个语境,把OCL表达式和被约束的模型元素连接在一起。OCL约束的语境可以是一个类或一个操作。这些约束可以表示在图上或者写在一个独立的文本文档中附加到该模型,采用什么方式将约束与其语境联系在一起,依赖于用什么风格描述约束。如果约束表示在图上,那么约束可以放在表示约束语境的符号的附近或内部。例如,如果约束的是类,那么可以放在类的图标的内部。图12.5表示的是图12.1表示的账户类,附加到该账户的约束指明了该账户实例的余额必须在所指定的范围之内。图12.5简单约束约束也可以如图12.1所示,用附加到模型元素的注解(note)表示。选择什么方法表示约束纯粹是一个表示风格的问题。代替在图上表示约束,也可以用纯文本形式表示约束。在这种情况下,必须明确地指出语境。约束必须从语境声明开始。语境声明由关键字‘context’和约束的类名或操作名组成。图12.5所示的约束用纯文本形式书写如下:关键字‘inv’指明了这个约束是一个不变量。类不变量说明的特性是,在所有时间点上这些属性值必须为真。这里表示的是在任何时候存储在余额属性的值必须大于0而小于250000。其他类型的约束将在12.7节讨论。约束中的术语‘self’指的是当前语境对象。由于约束总是针对当前语境计值的,所以‘self’是可选的,然而使用self可以使约束容易阅读。在本章的其余部分常常会把self插入到约束中。这个约束也说明了如何用OCL表示访问一个对象的特征(feature),即在表示要访问的对象的表达式的后边,添加一个圆点,然后写出特征的名称。选择这种表示方法是为了与Java和C++中访问类的特征时使用的点表示法一致。这种表示法允许在形式上有两个变化,即对语境对象可以提供一个可选名称,对约束本身也可以给一个名称,使得在一个复杂模型中可以更方便地引用指明的约束。例如,如果将上述语境对象命名为‘acc’,约束命名为‘accountLimits’,则上述约束可表示如下:12.4导航表达式约束的使用并不只限于类的不变量,例如在12.1节给出的例子说明,有些约束是对某些模型元素之间的关系加以限制。为此,OCL必须提供一些方法,引用在一个给定约束中涉及到的相关模型元素。非形式地说,OCL应当能够表示从一个语境对象开始,沿着链接得到其他对象,以确定所需要的模型元素。由于这个过程需要遍历这个对象网的一部分,所以称表示这些对象的表达式为导航表达式。我们将使用图12.6中的类图,说明OCL表示法是如何构成导航表达式的。这个图表示的是一个公司的人事部门所维护的信息模型。图中,公司(company)是作为由许多部门(department)聚合而成的聚合对象而被模型化的。公司中每个雇员(employee)被分配到一个部门。人员(person)类的自反关联表示公司的某些人是被谁管理。限定关联是公司可以通过对雇员是唯一的工资号(payrollnumber)访问该雇员。图12.6人事系统的简单模型人员类和公司类之间的关联表示了人员为该公司服务的工作关系。作为关联类定义的合同(contract)这个关系记录着雇用合同的细节。它记录了雇员开始工作的日期(startDate),并维护与工资级(grade)类的关联。工资级类的实例记录了该组织内具体的工资级的工资额(salary)。12.4.1跟随链接(Followinglinks)导航的基本形式是从一个对象到另一个对象的链接,每个链接都是某个关联的一个实例。所以导航可以通过标明被遍历的关联来描述。穿过一个关联的导航是用在语境对象名之后,用前面对属性使用过的点表示法,添加一个圆点,再写上该关联端的远端的角色名表示。这个表达式的值是通过这些指明的链接,当前链接到该语境对象的对象集合。例如,给定图9.6所示的类和关联,下述表达式表示的是在当前时刻在该部门工作的雇员的集合。如果一个关联没有角色名,可以用该关联远端的类名代替,但开始字母应当小写。例如,下述表达式引用的是该公司所有部门的集合。这个例子也说明,对导航表达式而言,聚合和普通关联并没有什么不同。如果用类名代替角色名有意思含糊不清的危险,则不能使用类名。例如,如果在一对类之间有两个关联,则必须在关联端点添加适当的角色名,以无二义地构成所需要的导航表达式。12.4.2对象和聚集(collection)导航表达式表示的是从语境对象出发,沿着指定的链接得到的对象。但是,依赖于遍历的关联的重数,这些对象的个数也不相同。例如,上述两个表达式,一般地将得到一个以上对象,即一个部门的全体雇员和一个公司的所有部门。相反地,下述表达式表示的是一个雇员所属的部门和该雇员的管理者,在所给出的关联定义下,不可能返回一个以上对象。一般地,在OCL中,把可能返回多于一个对象的导航表达式说成是返回一个聚集,而与聚集相对的简单地说返回单个对象(singleobjects)。由于每当需要时OCL都允许将单个对象作为聚集处理,所以考虑导航表达式最简单的方式是,把每个导航表达式都看作一个对象聚集。在某些情况下,聚集的特性很重要,我们将在12.5节进一步讨论。12.4.3迭代遍历导航表达式并不限于沿着一个关联导航。它也可以通过由用点号隔开的角色名或类名的一个序列,指明更复杂的导航路径。例如,下列表达式表示了为该公司工作的所有雇员。我们可以设想,这个表达式是用一步一步的方式求值的。首先检出的是该公司的所有部门组成的聚集,然后接着对每个部门,一一检出在该部门中工作的所有雇员的聚集,这些人员聚集合并到一起构成一个大聚集,它包括为该公司工作的每一个人。这个大聚集就是这个表达式返回的值。12.4.4遍历限定关联限定关联可以像一般关联一样用在导航中,但是它又提供了确定个别对象(individualobjects)的附加能力。当导航向着限定符方向进行时,限定关联和非限定关联没有什么不同。例如,下述表达式表示的是一个人为之工作的那个公司。而当导航沿相反方向进行时,限定符提供了检出已知工资号的特定雇员的一种方法。下述表达式检出的雇员,如果存在,其工资号是314159。这种表示可以与子序列导航或被选出的属性自由组合。例如,下述表达式返回的是工资号为314159的雇员的管理者。遍历未指明限定符值的限定关联是可以的。在这种情况下返回的是所有被链接的对象。例如,下述表达式表示的是公司的所有雇员的聚集。12.4.5使用关联类我们也可以用角色名或类名,像通常那样
三七文档所有资源均是用户自行上传分享,仅供网友学习交流,未经上传用户书面授权,请勿作他用。
本文标题:第12章约束
链接地址:https://www.777doc.com/doc-2242726 .html