测量对象用的面向对象的框架机制 一般说来,本发明涉及数据处理领域。更具体地说,本发明涉及面向对象的框架机制。
1948年EDVAC计算机系统的研制往往被引用为计算机时代的开始。从那时以来,计算机系统已经发展成为许多不同领域使用的极其复杂的装置。在计算机的早期,软件与硬件是密不可分的,两者是一起出售的。但是,近年来,软件变得可以独立于任何硬件地出售,然后可以在一个兼容的计算机系统上安装和使用。
“出售”计算机软件时,所述软件的所有权一般并不转让给买主,而是买主在伴随着所述软件地许可证协议中包含的某种条件或条款下得到使用所述软件的许可。随着计算机网络的普及,现在许多人可以访问并运行一种可以在网络上得到的特定的软件程序。有些软件的许可证允许较多的用户使用,但将同时使用的用户数限制在一个小得多的数目上。在这样的一种环境下,必须监视软件的运行,以保证网络上计算机软件的运行不违反许可证协议。当计算机软件运行时对它进行的任何一种监视,在这里都称作测量(Metering)。
还会出现在计算机软件运行时要求监视的其他情况。一种这样的情况便是对计算机软件的性能执行基准检查程序(Benchmarking),以确定程序的不同部分运行的频繁程度,并测量整个系统的性能。有许多不同的情况要求对计算机软件进行测量。
过去,计算机已经编有测量软件。一般说来,测量软件一直都是按照要测量的特定程序的特定要求而有针对性地开发的。不同的计算机程序的特定测量要求可能差别很大,然而,在不同的程序之间,许多测量功能却又是类似的。但是,现有技术测量软件中的差异,妨碍了许多测量代码从一个计算机程序再用到另一个计算机程序上。一般说来,每一个不同的计算机程序都有它自己的习惯、完成要求测量的专门途径,这些都不容易修改来适应任何一个新的或不同的计算机程序。
随着面向对象(00)编程技术的发展,计算机程序由许多对象组成,其中的每一个都含有数据和相关的操作或对这些数据进行操作的方法。在面向对象的环境中,测量的含义是测量具有计算机程序执行时被调用的方法的对象的某些参数。但是,即使是在面向对象编程的环境中,也必须对所要求的测量功能的细节进行编程以适应所要求的测量环境。没有一个易于剪裁和扩展来在特定的测量环境中测量一种计算机程序的机制,编制和维护测量程序所需的时间就会太长,费用过于高昂。
按照本发明,测量对象用的面向对象的框架机制提供一种体现测量计算机程序所需的步骤的基础结构和一种扩展框架以适应特定测量环境的机制。某些核心功能由框架提供,后者与框架用户提供的可扩展的功能交互作用。框架的结构使得程序员可以用一个不论测量环境规定的参数特定结合如何都是稳定的接口,来确定适用于测量环境的条件和参数。可扩展的功能使得新的测量环境容易利用所述框架来实现。这样,框架就允许有一个通用的编程接口,以便利用这个易于剪裁来包括新的或改变了的参数的框架来测量对象。框架通过提供一种通用的编程接口和提供已经建立好的易于扩展来实现要求的测量环境的类,大大地简化了程序员开发测量一种面向对象的计算机程序的代码的工作。
本发明的框架机制是利用面向对象的技术设计和构造的。不熟悉面向对象的技术或面向对象框架机制的读者应该阅读最佳实施例描述中面向对象的概述部分。
图1是框架机制例子的种类示意图;
图2至图6是图1示例框架机制的类示意图;
图7是图1至图6框架机制例子用的对象示意图;
图8是最佳实施例中用的计算机系统方框图;
图9是按照最佳实施例完成框架机制核心功能用的步骤的流程图;
图10是按照最佳实施例的教导构造的框架机制的种类示意图;
图11-17是按照最佳实施例的教导构造的框架机制的类示意图;
图18是表示扩展图10-17的框架来实施四种特定测量功能的例子的类示意图;以及
图19是图18测量例子的对象示意图。
概述-面向对象技术
正如在摘要部分讨论的,本发明是利用面向对象的的框架技术开发的。熟悉面向对象的框架技术的读者或许希望跳到本说明书详细描述的部分。但是,刚接触框架技术或一般说来刚接触面向对象技术的读者,应该阅读本概述部分,以便更好地理解本发明的好处和优点。
面向对象技术和过程技术
尽管本发明只涉及特定的面向对象技术(亦即,面向对象框架技术),但是读者必须明白,一般说来,面向对象技术与传统的基于过程的技术(往往称为过程技术)有着明显的差别。虽然这两种技术都可以用来解决同样的问题,但是,对所述问题的最终解决方案总是十分不同的。这个差异来自这一事实,即过程技术的设计焦点与面向对象技术的完全不同。基于过程的技术的焦点是在解决问题的整个过程上;而面向对象技术的焦点是如何将问题分割成为一组自治的实体,它们共同工作来提供解决方案。面向对象技术的自治实体被称为对象。换句话说,面向对象技术之所以明显地不同于过程技术,是因为问题被分割成一组互相合作的对象,而不是形成互相交织的计算机程序或过程的层次结构。
术语”框架”
对于熟悉面向对象设计的人具有特定意义的术语或短语是一直在演变的。但是,读者应该注意,在面向对象的技术中,最不严格的定义之中的一个就是框架一词的定义了。对于不同的人框架一词有着不同的意义。因此,比较两个作为建议提出的框架机制的特性时,读者必须小心,以保证这一比较确实是”苹果对苹果”的比较。正如在后面的段落中将会变得更加清除的,术语框架在本说明书中用来描述一种已经设计好具有核心功能和可扩展功能的面向对象的机制。核心功能是框架机制中不会被所述框架购买者改变的部分。另一方面,可扩展部分是框架机制中明确地为要由所述框架购买者剪裁和扩展而设计好的部分。
面向对象的框架机制
尽管一般说来,框架机制可以恰当地表征为一种面向对象的解决方案,然而,框架机制与基本的面向对象解决方案之间却有着根本性的区别。差别在于,框架机制是以这样的方式设计的,即,允许和促进解决方案某些方面的剪裁和扩展。换句话说,框架机制高于对问题的解决方案。机制提供一种活的解决方案,它可以剪裁和扩展,以满足随着时间推移而改变的个性化的要求。当然,框架机制的剪裁/扩展的质量对购买者(下文称作框架消费者)来说是极有价值的,因为框架剪裁或扩展的费用要比替换或重新拟定现有的解决方案的费用要低得多。
因此,当框架的设计者着手解决特定的问题时,他们做的比仅仅设计各个对象并考虑这些对象如何相互联系要多。他们还要设计框架的核心部分(亦即框架中不会被框架消费者剪裁和扩展的部分)和可扩展部分(亦即框架中准备要剪裁和扩展的部分)。最后,框架机制的极终价值不仅在于对象设计的质量,而且还在于涉及哪些方面代表核心功能,哪些方面代表可扩展功能的设计选择。
动物园管理框架-一种说明性的框架机制
虽然本专业的技术人员会认识到,框架设计必然是一种缠结的和迭代的过程,但是,下面的段落将提出一种十分简单的框架机制用的说明性的设计选择。应该明白,尽管这只是一种框架示例,但是,它在本说明书中用来举例说明并解释清楚框架机制,使得读者能够理解和欣赏本发明的好处和优点。
框架设计者通过从所谓问题域中选择对象,来确定一个框架机制需要哪些对象。问题域是所考虑的特定问题的一种抽象的视图。为这种说明性的框架机制选择的问题域例子是动物园管理。特定的问题是,设计一种机制来帮助动物园饲养员(keeper)照料和喂养动物园的动物。在我们的动物园管理框架(ZAF)的例子中,面向对象的框架设计者会查看动物学问题域并决定,任何一种动物园管理框架都需要涉及代表动物园饲养员和动物之间关系(亦即动物园饲养员如何照料动物)的机制。框架设计者还很可能认识到,动物园的动物通常都生活在笼子、围栏、槽子和其他种类的禁闭(containment)单元里。因此,我们的框架设计者会把所述框架会涉及代表所有这些基本实体和关系的机制这一想法作为出发点。
如何设计动物园管理框架
为了开始这个设计过程,我们框架的设计者很可能从所谓种类示意图开始。种类示意图用来描述高层次的框架机制以及这些机制相互之间如何联系。图1就是动物园管理框架的例示框架的种类示意图。图1中所用的符号表示法以及本说明书中使用的符号表示法在本说明书末尾(43-49页)的符号表示法段落中将有详细的说明。种类示意图中的每一个机制都代表一组完成特定功能的对象。为了说明方便起见假定,我们的框架设计者决定,动物园管理框架应该包括四个高层次的机制:动物园管理机制、动物园饲养员机制、动物机制和禁闭装置机制。
如图1所示,动物园管理机制企图利用动物园饲养员机制来管理动物园。因此说,动物园管理机制与动物园饲养员机制具有使用(using)的关系。(请再一次参考本说明书符号表示法段落,看看这种关系的解释以及本说明书中所用的其他符号表示法。)
正如所讨论的,动物园管理机制企图负起动物园管理框架的总体控制的责任。因此,动物园管理机制负责调度动物园饲养员机制的操作。请注意,我们的框架设计者把动物园管理机制设计成动物园管理框架的核心功能,这意味着,它被设计成将来没有剪裁和扩展的可能。种类框中的C表示这一事实。还请注意,动物园管理机制与动物园饲养员机制之间的使用关系也设计成框架消费者不能进行最终的剪裁。
动物园饲养员机制企图在一般情况下负责照料与喂养动物园的动物。因此,它使用动物和禁闭装置机制来完成它的任务。但是,与动物园管理机制的设计不同,我们的框架设计者已经把动物园饲养员机制设计成可扩展功能,这又意味着所述框架的消费者可以进行修改和扩展,以满足将来照料与喂养的要求。这一事实在动物园饲养员机制种类框中用E表示。
我们的框架设计者已经把动物机制设计成动物园的动物与动物园饲养员之间相互作用的动物一方。因为动物中的动物头数总是不断地改变的,所以类似地动物机制也设计成可扩展功能。禁闭装置机制通过代表诸如围栏、槽子、笼子等各个禁闭装置而与动物园饲养员机制相互作用。和动物机制一样,禁闭装置机制设计成一种扩展功能,使得它能够处理将来的剪裁和扩展要求。但是,在这里请注意,尽管动物园饲养员、动物园的动物和禁闭装置都设计成可扩展功能,但是,这些机制之间的关系被设计成动物园管理框架的核心功能。换句话说,尽管想要在动物园饲养员、动物园的动物和禁闭装置方面,给动物园管理框架消费者灵活性,但是,并不希望允许动物园管理框架的消费者去改变这些机制之间的相互关系。
接着,我们的框架设计者会设计构成图1所示机制的类和关系。类是一组类似的对象的定义。这样,类可以看成对象的抽象,或者一种类型对象的定义。从计算机系统的观点来看,单个的对象代表封装起来的一组数据和计算机系统对这些数据完成的一个或一组操作。事实上,在可靠的计算机系统中,对于由对象控制的信息只能通过对象本身来访问。这就是为什么把包含在对象中的信息说成是由对象封装的。
每一个类的定义,都包含数据定义和操作定义,前者定义对象所控制的信息,而后者定义对象对于所述对象所控制的数据完成的一个或几个操作。换句话说,类的定义通过定义在所定义的数据上完成的一个或一组操作,来定义一个对象如何动作以及对其他对象作何反应。(请注意,操作有时称为方法、方法程序和/或成员函数。)当放在一起时,所定义的一个或一组操作和数据被说成是对象的行为。于是,实质上,类的定义定义了它的一个或多个成员对象的行为。
图2是我们的框架设计者为动物园管理框架设计的面向对象的类示意图。每一个类的表达都包含它与图1所示的机制的关系。例如,动物园饲养员类标明了来自动物园饲养员机制。动物园管理框架的基础类包括:动物园管理员类,它是动物园管理机制的一部分;动物园饲养员登记类,它也是动物园管理机制的一部分;动物登记类,它是动物园饲养员机制的一部分;动物园饲养员类,它也是动物园饲养员机制的一部分;禁闭装置登记类,它也是动物园饲养员机制的一部分;动物类,它是动物机制的一部分;禁闭装置类,它是禁闭装置机制的一部分。
请再注意,这些类之间的关系被设计成动物园管理框架的核心功能,动物园管理框架的消费者无法对其进行最终的修改。
动物园管理员类是负责对动物园管理框架全面控制的对象的定义。再说一次,面向对象的类只定义那些能相互作用以便对问题提供解决方案的对象。但是,利用类定义的特性,我们就能够理解框架机制的对象如何设计来提供一个能够剪裁和/或扩展来满足将来要求的活的解决方案。
动物园管理员类预定有与动物园饲养员登记的使用关系。我们的框架设计者把动物园管理员和动物园饲养员登记类设计成具有动物园管理框架的核心功能,因为我们的设计者决定动物园管理框架的消费者不应被允许改变这些类定义的成员对象的行为。与动物园饲养员类具有所谓容纳参考关系(contains by reference relationship)的动物园饲养员登记,简单地是这样的一类,即所述类定义关于所有动物园饲养员对象的容器的对象。因此,动物园饲养员登记包括list_zoo_keepers()操作的定义。正如后面将要描述的,这一操作负责向要用动物园饲养员对象清单的其他对象提供这一清单。
图3表示动物园管理员类较低层次的视图。因为动物园管理员类型的对象负有对动物园管理框架进行全面控制的责任,所以动物园管理员类设计得包括完成面向动物园管理的任务的操作。所述类的定义包括下列5个操作:5_minute_timer(),add_animal(),add_containment_unit(),add_zoo_keeper()和start_zoo_admin()。
start_zoo_admin()操作负责启动动物园管理框架。就是说,用户或系统管理员与start_zoo_admin()的操作交互作用,通过动物园管理框架开始动物园的管理。一旦启动,我们的框架设计者设计了start_zoo_admin()操作来对5_minute_timner()的操作初始化。每5分钟,5_minute_timer()操作指令动物园饲养员对象出去并检查动物。add/delete_zoo_keeper()的操作负责与动物园管理框架的用户交互作用,来定义外加的动物园饲养员(亦即,外加的动物园饲养员类),来增加动物园饲养员(亦即,动物园饲养员对象),和去除动物园饲养员类和/或对象。正如在后续的段落中将会变得清楚的,每一个动物园饲养员对象负责完成一个特定的动物园任务。因此,动物园管理框架的用户自然很想增加一个动物园饲养员定义和对象,来处理外加的动物园任务或去除一个不再需要的定义或对象。正如将会看到的,这一灵活性是通过将动物园饲养员机制设计成可扩展的功能而提供的。
像add/delete_zoo_keeper()的操作一样,add/delete_animal()的操作是负责与用户交互作用,来定义动物园动物的类和对象和去除不再需要的类和对象。再者,动物园十分自然地需要增加和去除动物。像add/delete_zoo_keeper()的操作一样,add/delete_containment_unit()的操作是负责定义新的禁闭装置类和对象和去除不再需要的类和对象。我们的框架设计者再次以这样的方式来设计动物园管理框架,使得通过把动物和禁闭装置机制设计成可扩展的功能来提供这种灵活性。
回头参见图2,动物园饲养员类定义与动物登记、动物、禁闭装置登记和禁闭装置类具有使用关系。既然动物园管理框架的价值是通过允许动物园管理框架消费者能够剪裁和扩展动物园饲养员、动物、和禁闭装置类来提高的,所以这些类被设计成可扩展的功能。但是,改变动物和禁闭装置登记类的行为,就会使动物园管理框架的基本操作瓦解。因此,这些类被设计成动物园管理框架核心功能。
动物园管理框架中的类和种类不是被描述成核心功能,就是被描述成可扩展的功能,然而指出以下一点是很重要的,即这里使用的”核心功能”一词是与使框架以要求的方式操作的要求广泛地相关的。简而言之,框架的核心功能是任何一个使用框架的程序都会完成的功能。核心功能的要求可能是框架的结构提出的(例如,通过指定某些类作为核心功能),或者可能由决定框架消费者可以如何利用框架的功能要求提出的。这样,核心功能不仅包括设计成核心的类和类关系,而且还可能包括为使框架正确地起作用而以特定的方式实现的可扩展的类。换句话说,可扩展的功能是框架中设计成准备由框架消费者剪裁的部分,剪裁的性质和程度是由框架的核心功能的要求确定的(亦即整个框架功能是由框架的结构和功能要求决定的)。例如,动物类已设计成动物园管理框架的可扩展的功能,使得动物园管理框架可以被剪裁来适应不同类型的动物。但是,剪裁可扩展的功能的能力并不意味着剪裁的性质可以违反由动物园管理框架的核心功能决定的基本结构(例如,通过将动物类剪裁到这样的程度,以至它不再能合理地说是代表动物的类型)。
图4是动物园饲养员类的类示意图。但是,在描述图4细节之前,值得指出的是,图4所示的类定义是按非常简单的被称为类层次结构的次序排列的。代表类层次结构中最一般化/最抽象的类,例如动物园饲养员类,被称为层次结构的基础类。类层次结构中类的次序是从最一般的到最不一般的(亦即从一般到特殊)。较不一般的类(例如,喂养员类)被说成是从较一般的一个或多个类(例如,在这种情况下是动物园饲养员类)继承一些特性。这样,类定义喂养员、兽医和温度控制员被说成是动物园饲养员类的子类。以后讨论涉及图5时还将更详细地介绍继承机制。
如图4所示,动物园饲养员类定义只包含单个操作定义,check_animals()(检查动物)的操作定义。读者还应注意,动物园饲养员类定义被标注为抽象类。抽象类预定不具有作为其成员而产生的对象,而是用来为其子类定义公共接口/协议。当类的操作定义中至少有一个是纯虚拟操作定义时,所述类被称为抽象类。虚拟操作定义是只为所述操作的子类定义而定义公共接口的的而设计的。换言之,实际行为的设计(即,数据和操作)听任所述子类。在动物园饲养员类定义的情况下,喂养员、兽医和温度控制员子类给包含在动物园饲养员类中的纯虚拟操作定义check_animals()定义具体的实施过程。当操作被置0时,所述操作被标志为纯虚拟操作。
但是,指出以下一点是很重要的,即,纯虚拟操作定义的公共接口必须被所有的子类所兑付(honored),以便请求对象(被称为客户对象)可以使用子类成员对象(被称为服务者对象),而不必知道服务者对象的特定子类。例如,无论何时,只要动物园管理员类所定义的对象需要完成特定的动作,它就与动物园饲养员对象交互作用。因为对这些对象的接口是为操作check_animals()而定义在抽象的基础类动物园饲养员中的并保存在子类的定义中的,所以,动物园管理员对象无需具0体地掌握任何服务者对象的子类。其作用是动作的需要(亦即在动物园管理员方面)和进行所述动作的方法(亦即,通过动物园饲养员子类的对象)脱钩。利用了抽象类的这一特性的设计(像动物园管理框架的设计)被称为是多态性。
多态性对于面向对象的框架设计是极其重要的,因为它允许做某件事情的方法(称为实现)可以改变或扩展,而不会影响取决于动作实际完成的事实的机制。换句话说,客户对象只需要知道某个对象完成某种功能,而无需知道这些功能是如何实际完成的。这就是使得恰当设计的框架能够容易地剪裁和扩展以满足将来的要求的方法。
正如前面讨论的,我们的框架设计者已经这样地设计了动物园管理框架,使得动物园饲养员对象与动物和禁闭装置对象交互作用,以完成它们的任务。图5是抽象类动物的类层次结构的类示意图。既然动物类定义负责代表动物园动物的特性和行为,框架的设计者以一种能够反映这一责任的方式来设计抽象的类动物。正如所示,动物类定义例子包括数据定义feed_freq(喂食频繁程度),location(位置)和temp_range(温度范围)以及操作定义get_temp_range()(获得温度范围),feed()(喂养),needs_food()(需要食物),needs_vet_visit()(需要参见)和vet_visit()(参观)。
为了达到概述这一框架的目的,无需详细地说明每一个定义。但是,数据定义temp_ange和操作定义get_temp_range()和feed()是考虑周到的框架设计选择的好例子。
操作定义feed()预定进行动物的实际喂食(亦即通过未示出的特定的喂食设备)。feed()操作是纯虚拟操作。这再次意味着所述类是这样设计的,使得进行其需要的功能的实际机制听任子类来定义。在作为子类成员而建立的对象具有特殊的需要的这样一种情况下,请求子类定义是一种良好的设计选择。例如,在动物园管理框架中,每一类动物很可能需要特殊的喂食装置,这不仅使一般性的操作feed()难以定义,而且是没有意义的。
通过比较,框架设计者明确地把操作get_temp_range()设计得它不是一个纯虚拟操作定义。这就是说,get_temp_range()一般地定义为内定操作。这样,它被认为是一个虚拟操作。内定操作用来向子类提供一般性的功能。子类可以简单地使用内定操作,或者它们可以通过再定义来剪裁或扩展内定操作。内定操作的再定义被称为是内定操作的覆盖(overriding)。
mammals(哺乳类动物)是类animals(动物)的子类,这样mammals继承了animals类的全部特性。请注意,mammals类也设计成抽象类,这再次意味着它被设计成它不能建立对象作为其成员,而是设计成为其子类提供公共接口。子类mammals还有子类carivore(食肉类动物)和herbivore(食草类动物)。
既然操作feed()的定义要留给子类,子类camivore和herbivore每一个都有它们自己的feed()操作的定义。这又是一个良好的设计选择,因为食肉的carnivore会有与食草的对手有着不同的需要。
temp_range(温度范围)是符合特定动物自然习惯的温度范围的数据定义,而get_temp_range()(获得温度范围)操作定义预定检索特定动物的temp_range,并将其返回给请求的客户对象。子类reptils(爬行动物)含有它自己的temp_range定义并有它自己的get_temp_range()操作定义。动物园管理框架用这种方法设计,以便指出数据定义像操作定义一样是可以超越的。因为许多reptils(爬行动物)生活在沙漠条件下,那里晚上可能很冷,而白天很热,所以内定操作get_temp_range()在子类reptils(爬行动物)被超越,包括时间和温度信息(在图5中未明确示出)。这是另一个良好的设计选择,因为它允许动物园管理框架通过允许根据一天的时间以及当前禁闭装置本身的温度来调节温度,来处理不同于其他禁闭装置的reptils(爬行动物)的禁闭装置。
图6是表示禁闭装置类较低层次视图的类示意图。禁闭装置类含有虚拟的操作adjust_temp()(调节温度)定义。adjust_temp()定义确定了实际调节动物园禁闭装置中温度用的接口和机制(亦即通过未示出的采暖和制冷机制)。
动物园管理框架对象如何相互作用
除了构成特定问题解决方案的对象的设计以外,我们的框架设计者还必须设计各个对象如何相互作用。换句话说,对象必须利用设计它们时用的手段相互作用。正如所讨论的,以对象定义的操作对所述对象定义的数据进行操作的方式被称为对象的行为。对象的特征是它是一种自治的实体,当与其他对象相互作用时,每一种对象都表现出一致的行为是非常重要的。一致的行为之所以重要,是因为对象依赖于其他对象的一致行为,使得它们表现出一致的行为。事实上,一致的行为是如此之重要,以致对象的行为往往被称为所述对象与其他对象的合同(contract)。当对象没有表现出一致的行为时,它被说成是违反了与其他对象的合同。
当一个对象的操作需要访问由另一个对象控制的数据时,它被认为是第二个对象的客户。为了访问由第二个对象控制的数据,客户的一种操作将调用或启用第二个对象的一种操作,来取得被所述对象控制的数据。然后,被调用的对象的一种操作(亦即,在这种情况下是服务者操作)被执行,来访问和/或处理由被调用的对象控制的数据。
图7是一个对象示意图,表示动物园管理框架的示例对象如何交互作用,以便在动物园的运作上协助动物园人员。为了达到这个概述的目的无需详细地分析动物园管理框架所有对象的相互反应。但是,读者应该再考察一下下列简单的控制流程,以便对对象如何相互作用来解决问题获得基本的理解。
如上所述,对象是作为一类的成员而建立的。所以,动物园管理员Zelda[对象705]是Zoo Administrator(动物园管理员)类的成员(实际上是唯一的成员)的对象。这样,对象Zelda负责动物园管理框架的全面控制。所有的动物园饲养员对象都用动物园饲养员登记对象[对象700]登记。所以,对象Zelda通过调用动物园饲养员登记对象的操作list_zoo_keepers()(列出动物园饲养员清单)[步骤1],来得到当前动物园饲养员清单。动物园饲养员登记对象是作为动物园饲养员登记类的成员而建立的。为了举例说明,假定作为Zelda的操作5_minute_imer()(5分钟定时器)的一部分,每5分钟出现一次。然后,动物园饲养员登记对象以动物园饲养员清单作响应[步骤2]。动物园饲养员清单包括温度检查员Tina[对象714]、兽医Vince[对象740]和动物喂养员Fred[对象752]。每一个动物园饲养员都是作为动物园饲养员类的成员建立的。具体地说,对象温度检查员Tina、兽医Vince和喂养员Fred分别是温度控制员、兽医和喂养员子类的成员。
一旦动物园饲养员清单已经返回给对象Zelda,对象Zelda便通过调用指示动物园饲养员对象的操作check_animals()(检查动物),向动物园饲养员清单的每一个动物园饲养员发指令[所示只呼叫温度检查员Tina-步骤3]。请注意,对象Zelda无需了解动物园饲养员清单中的动物园饲养员的类型、动物园饲养员清单中动物园饲养员对象的个数或动物园饲养员对象的专门特性。对象Zelda使用同一个接口(亦即,操作check_animals())与每一个动物园饲养员对象通信。然后,这要由各个动物园饲养员对象完成他们为之建立的任务。每一个动物园饲养员对象都使用他们自己的操作check_animals()来完成他们所分配的任务。例如,对象Tina的操作check_animals()通过调用list_animals()(列出动物清单)操作从动物登记清单对象检索当前的动物清单[步骤4],然后通过调用操作list_cont_unit()(列出禁闭装置清单)从禁闭装置登记对象检索禁闭装置清单[步骤6]。检查动物清单,对象Tina的操作check_animals()确定,目前在动物园中登记的只有两只动物,蛇Sam[对象728]和狮子Simba[对象718]。
然后,对象Tina的操作check_animals()调用操作get_temp_range()(获得温度范围)从对象Sam和Simba取得温度范围[步骤8和10]。一旦已经返回温度范围,对象tina的操作check_temp_range()便确定哪一个禁闭装置关着各个动物,然后,调用适当的禁闭装置(亦即,对象Simba的狮子笼7和对象Sam的蛇坑3)的操作adjust_temp()来调整这些禁闭装置的温度[步骤12和13]。
然后,每一个禁闭装置的操作adjust_temp()通过以与每一个禁闭装置所关的动物相适应的方式调整温度。(就是说,根据时间和温度为蛇坑3调整温度,而只根据时间为狮子笼7调整温度)。读者应该注意,操作check_animals()与操作adjust_temp()的关系是多态性的。换句话说,对象Tina的操作check_animals()无需掌握关于每一个操作adjust_temp()如何完成其任务的专门知识。操作check_animals()只需要遵守接口并调用操作adjus_temp()。在这之后,就所述轮到各个操作adjust_temp()去以适当的方式完成它们的任务。
在这一点上,值得再一次指出的是,动物园管理框架机制是一种极其简单化的框架机制,把它呈现在这里是为了帮助新手读者理解某些基本的框架概念,以便最好地欣赏本发明的好处和优点。参照下面的详细描述之后,这些好处和优点将变得更加清楚。
详细描述
图8表示按照本发明的计算机系统800的方框图。最佳实施例的计算机系统是诸如AIX平台等的计算机系统。但是,本专业的技术人员都会认识到,本发明的机制和装置同样地适用于任何一种计算机系统,而不论所述计算机系统是复杂的多用户计算机装置还是单用户工作站。正如图8分解视图所示,计算机系统800包括主要或中央处理单元(CPU)810,后者连接到主存储器820、海量存储器接口830,终端接口840和网络接口850。这些计算机组件通过使用系统总线860相互连接。海量存储器接口830用来将海量存储器(诸如DASD(直接存取存储装置)855)连接到计算机系统800。一种特定类型的DASD装置是软磁盘驱动器,它可以存储数据并从软磁盘895读出数据。
主存储器820含有应用程序822、对象824和操作系统828。计算机系统800利用众所周知的允许计算机系统800的程序表现得好象它们只访问巨大的单一的存储实体(在这里称为计算机系统存储器)而不是诸如主存储器一类多个较小的存储实体的虚拟地址机制以及DASD(直接存取存储装置)855。因此,尽管如图所示,应用程序822、对象824和操作系统828驻留在主存储器820上,但是,本专业的技术人员都会认识到,这些程序并不一定要同时驻留在主存储器820上。请注意,这里用的术语”计算机系统存储器”一般地指计算机系统800的整个虚拟存储器。
操作系统828是诸如AIX一类适当的多任务操作系统,但是,本专业的技术人员都会认识到,本发明的精神和范围并不局限于任何一种操作系统。操作系统828最好支持诸如,例如,C++语言所提供的面向对象的编程环境。一个或多个应用程序822给计算机系统提供一种编程环境,并包括对象测量框架机制870,后者最好是面向对象的框架机制。框架机制870含有能够在CPU810上执行的指令,并可以存在于计算机800虚拟存储空间的任何地方。
尽管所示计算机系统800只含有单个主CPU和单个系统总线,但是本专业的技术人员都会看出,本发明可以利用具有多个CPU和/或多个总线,或者只含于单一装置中或者分布在分布式处理计算机系统中的计算机系统来实现。另外,在最佳实施例中所用的各个接口,每个都单独地包括完全编程微处理器,用来从CPU810分担计算任务繁重的处理。但是,本专业的技术人员都会看出,本发明同样适用于只使用I/O适配器来完成类似功能的计算机系统。
终端接口840用来直接把一个或多个终端865连接到计算机系统800。这些终端865可以是非智能型的或完全可编程的工作站,用来使系统管理员和用户能够与计算机系统800通讯。
网络接口850用来把其他计算机系统和/或工作站(例如,图8中的875和885)以网络方式连接到计算机系统800上。无论计算机系统800如何连接到其他计算机系统和/或工作站上,无论是用当前的模拟式和/或数字式技术,还是通过将来的某种联网机制连接到网络上,本发明都同样适用。指出以下一点也是很重要的,与计算机系统800连接的网络接口850的存在,意味着计算机系统800可以与一个或多个其他计算机系统或工作站进行合作处理。当然,这又意味着在主存储器820中所示的程序不一定都要驻留在计算机系统800上。例如,一个或多个程序驻留在其他系统内,并参与驻留在计算机系统800上的程序的合作处理。这种合作处理可以通过使用诸如远程过程调用(PRC)等众所周知的客户-服务器机制来完成。
在这一点上,指出以下一点是很重要的,即尽管本发明已经是(并且以后还是)以全功能的计算机系统来描述的,但是,本专业的技术人员都会看出,本发明可以利用软盘(例如,图8中的895)、CD ROM(光盘)或可记录介质的其他形式,或者通过某种电子传输机制作为程序产品销售。
本发明的对象测量框架机制
这里公开的对象测量框架机制提供一种测量计算机程序中对象使用人数的结构。扩展所述框架来测量在特定环境中的对象,就定义了一种”测量环境”。例如,通过扩展所述框架来测量一个或多个用户对对象的使用人数,就建立了一种针对所述特定任务而剪裁的测量环境。
通过在计算机系统800内提供框架机制870来测量对象的使用人数就提供了一种测量任何计算机程序中对象的一致的接口。框架机制870可以代替目前用来测量对象的所有专有系统。这将允许为实际上任何一种要测量对象的程序提供公用的程序员接口。这个公用接口大大地减轻了专用对象测量系统的编程和维护的开销。这样,这里公开的框架的一个主要的好处是,能够利用简单的易于使用由所述框架定义的接口来测量对象。
参见图9,按照本最佳实施例的对象测量框架完成包括对象测量方法900的各个步骤。无论何时,只要关于被测量对象的方法被调用,所述框架就被调用(步骤898)。一旦所述方法被调用,第一步是确定在执行所述方法之前是否要求前处理(亦即,”前逻辑”)(步骤910)。若需要执行前逻辑(步骤910=是),则为所有被测量的对象检索数据集(步骤920)。所述数据集包含属于被测对象的全部数据。接着,确定对应于被调用的方法的对象的配置(步骤930)。所述配置可以包括诸如所述对象是否一个组(suite)的成员、适用的使用阈值、要测量的方法以及所述对象的被测数据是存储在一个固定的位置还是分布在若干个位置等等的信息。一旦配置数据确定了(步骤930),就执行相应的前逻辑(步骤940)。前逻辑的一个适当的例子是当要测量一种方法的定时时,启动一个定时器。请注意,前逻辑可能包括对所述对象的被测数据的更新。一旦所需要的任何前逻辑都执行了,被调用的方法即被执行(步骤950)。
执行了被调用的方法(步骤950)之后,就确定是否要有任何后处理(亦即,有”后逻辑”需要执行)(步骤960)。若不要求后逻辑(步骤960=否),则方法900结束。若有后逻辑要执行(步骤960=是),则方法900首先检查被调用的方法用的配置数据是否已经检索(步骤962)。若被调用的方法执行了前逻辑,则配置数据以前在步骤920和930中已经检索,无需再检索。若配置数据以前未检索(步骤962=否),则检索所述数据集合(步骤970)并确定配置(步骤980)。接着,执行后逻辑(步骤990)。
对被调用的方法的被测数据的更新可能发生在前逻辑的执行过程之中(步骤940)或后逻辑的执行过程之中(步骤980)。在最佳实施例中,被测数据的更新是作为后逻辑的一部分由后逻辑完成的,让测量功能与被调用的方法并行进行或在其后进行,使得对所述方法的访问得到保证,而不会有明显的开销或延迟。更新被测数据的特定步骤取决于要完成的测量类型。例如,若要测量对象的使用人数,则将被测数据加一,以反映对象的又一次使用。若要测量对象的用户,而所述用户又是第一次调用所述对象的一个方法,则把调用所述方法的用户列入用户清单,或若一个用户以前调用过所述对象的一种方法,则给所述用户的计数加一。若要测量的是被调用的方法的定时,则在调用所述方法之前在前逻辑执行过程中(步骤940)启动定时器,并在后逻辑的执行过程中(步骤990)停止所述定时器。所述方法的执行时间作为后逻辑(步骤990)的一部分储存。如上面讨论的示例所示,框架870可以由程序员扩展来定义任意数目的不同的对象测量环境。
所示方法900中的步骤是顺序执行的,但也可以在多线程系统中并行地执行。事实上,与先有技术的测量系统相比,框架870提供的明显优点在于,方法和测量功能可以同时完成,以此减小完成测量功能所需的开销。多线程系统用一个线程执行所述方法,并用另一个线程执行测量功能。许多先有技术测量系统在取得访问权执行所述方法之前完成测量功能。这是防止超过许可证协议允许的用户数的用户执行所述方法的一个解决方法。但是,可以利用对象测量框架870实现的另一个解决办法是,每一次检查简单的状态寄存器之后调用所述框架时比准对欲执行的方法的访问权。若状态寄存器表明所述方法可以访问,则所述方法便被执行,并与所述方法并行或在其后执行测量功能。若测量功能确定,用户数加一的结果是用户数等于许可证协议允许的最大数目,则测量功能更新状态寄存器,指出所述方法不可以访问。用这样的方法,所述对象测量方法可以在没有先有技术测量系统所涉及的开销的情况下在多线程系统中完成。先有技术测量系统一般都要确定所需的测量类型,并在批准对所述方法的访问权之前进行繁琐的检查。
所述框架的最佳实施例是面向对象的这一事实,允许框架的用户利用诸如C++等已知的面向对象的编程环境,从定义在所述框架内的类建立子类,很容易定义所需的功能。本发明最佳实施例是面向对象的对象测量框架。尽管可以有许多不同的设计和实施方案,但是,下面将公开一个面向对象的对象测量框架的适当例子,来举例说明本发明的主要概念。
类的定义
图10是按照最佳实施例的对象测量框架机制的种类示意图。本专业的技术人员都会看到,图10中举例示出的种类代表封装数据特性和行为(或方法)的面向对象的编程类的集合。作为这些类的成员而实例化的对象储存在计算机系统800的主存储器820中。这些类可以在,例如,支持C++编程语言的计算机系统操作环境中实现。
这些类被分成六个种类(category):SOM Toolkit(SOM(IBM公司的系统对象模型(System Object Model))工具箱)、Principals(主角)、MeteredData(被测量的数据),Metering(测量)、Configurations(配置)和Thresholds(阈值)。除SOM工具箱以外,全都是可扩展的种类(用标志”E”标示),这意味着用户可以通过定义和实现作为框架定义的类的子类来扩展这些种类中的类。按照本发明,框架的实现并不一定需要SOM工具箱(用标志”N”标示),但是由于它在提供持久性(persistence)、定义好的元类(metaclasses)和这些类的子类用的方法方面所提供的便利,所以把它包括在这里最佳实施例中。SOM提供的一些好处是持久性和元类。Principals,MeteredData,Metering,Configurations和Thresholds这些种类中的每一种与SOM工具箱类都有着使用关系,表明这些种类中的类可以调用SOM工具箱。请注意,种类之间的关系是核心关系(用标志”C”标示),这意味着框架的用户不能修改这些关系。
图11是测量框架870顶层类示意图。SOM工具箱种类包括PersistentObject(持久对象)类和BeforeAfter(前后逻辑)元类。Principals(主角)类,SpecificPrincipals(特殊主角)类、MeteredSuite(被测组)类和MeteredEntity(被测实体)类都是Principals种类的成员。作为MeteredData种类的成员的类包括MeteredData(被测数据)、MeteredEntityData(被测实体数据)和SpecificMeteredEntityData(特殊被测实体数据)。作为Configurations种类的成员的类包括ConfigurationData(配置数据)、MeteredEntityConfiguration(被测实体配置)和SpecificMeteredEntityConfigurations(特殊被测实体配置)。作为Thresholds种类包括Threshold(阈值)类和SpecificThresholds(特殊阈值)。每一类中提供的方法未在图11中示出,但是,示于随后的几个图中。
图11举例说明所述框架中这些类之间的关系。MeteredData类、ConfigurationData类和MeteredEntityConfiguration类是框架的核心类。其余的类是可扩展类,而这些类之间的关系是框架核心功能的一部分。图11中在其名字上带有”Specific”(特殊)一语的各种类型的类代表定义任意数目的对象测量环境所要求的子类的任何数目的类。
如图11举例说明的,所述框架是极其灵活而功能强大的。程序员通过从框架已经定义的类适当地建立子类,就可以定义任意数目的测量配置或测量环境。事实上,图11的框架必须建立子类来完成要求的测量功能。图11举例在广义上表示本发明的框架,而参照图12-17的类示意图则能最好地理解最佳实施例的细节,这些附图举例说明完成若干个特定测量功能的子类。但请注意,最佳实施例中定义的特定测量功能是通过适当地建立子类可以实现的测量功能的类型范例,而所述框架机制明确地包括测量与计算机程序中的对象有关的任何一个欲测的参数用的任何一个和所有适当的子类。
最佳实施例用的SOM工具箱中各类的类示意图示于图12。SOM工具箱中的类是2.1版IBM的系统对象模型(System ObjectModel-SOM)工具箱的一部分。所述SOM工具箱只用来举例说明对象测量框架一个具体的实施方案的例子。请注意,图12的SOM工具箱提供与图11的BeforeAfter(前、后处理)元类和PersistentObject(持久对象)类对应的SOMMBeforeAfter(SOM前、后处理)元类和SOMPPersistentObject(SOM持久对象)类。尽管实现对象测量框架并不一定需要SOM工具箱,但是,通过建立子类它可以提供非常有用的机制来定义对象测量框架的许多类。SOMPPersistentobject(SOM持久对象)类是SOMObject(SOM对象)类的子类,SOMObject类的元类是SOMClass(SOM类)元类。SOMMBeforeAfter(SOM前、后处理)是通过从SOMClass(SOM类)元类和SOMObject(SOM对象)类建立子类而定义的元类。SOMObject(SOM对象)类是所有SOM类的根类。所有SOM类都必须是SOMObject的子类或它的子类中的一个。SOMObject定义一组提供所有SOM对象所要求的行为的方法。例如,somGetClassName()方法用来获得定义正在被调用的类的名字。
SOMMBeforeAfter(SOM前、后处理)元类提供两种在每次调用实例之前和之后调用方法的方法。sommBeforeMethod()在调用实例之前被调用,而sommAfterMethod()在调用实例之后被调用。SOM类的其他方法也在SOM工具箱中定义,但在这里不再描述。读者可以参考适当的SOM文献获得进一步的细节。参考图13的子类可以最好地理解对象测量框架870中用的SOM方法的细节。
参照图13,MeterUsage(测量使用人数)类、MeterConcurrentUsage(测量并行使用人数)类、MeterUser(测量用户)类、MeterLocation(测量位置)类和MeterTiming(测量定时)类都是Metering种类的成员,并代表定义不同测量类型的适当子类。这些元类中的每一种都对应于图11不同BeforeAfter(前、后处理)元类。每一个都有框架机制内的对象用来完成已定义测量功能的方法。例如,MeterUsage(测量使用人数)元类是定义来测量诸如实例化对象的使用人数或一般方法的使用人数的。它用sommAfterMethod()方法在关于对象的被调用的方法已经执行完之后用来测量对象的使用人数。MeterConcurrentUsage(测量并行使用人数)元类提供一种机制来测量对象的并行使用人数。调用sommBeforeMethod()方法在所述方法执行之前将对象的并行使用人数加一。类似地,调用somAfterMethod()方法在所述方法执行之后将对象的并行使用人数减一。
MeterUsers(测量用户)元类是定义来测量作为Principal(主角)类的子类的User(用户)类的使用人数。MeterUsers(测量用户)元类定义了两种方法。第一种getUserName()是一种内部方法,它确定哪一个用户(亦即,人)与被测量的对象相联系,并返回对应于用户(人)的用户实例。第二种是sommAfterMethod(),它在客户方法执行之后完成用户的测量功能。
MeterLocation(测量位置)元类定义来测量与Location(位置)对象(它是Principal(主角)类的子类)相联系的被测量的实体的位置。MeterLocation(测量位置)定义了getLocation()(获得位置)方法、changeLocation()(改变位置)方法和sommAfterMethod()(SOMM后处理方法)方法。getLocation()方法是再现与位置的被测量对象相联系的Location对象的内部方法。changeLocation()方法改变与被测量对象相联系的Location对象。sommAfterMethod()方法在客户方法执行之后完成位置测量功能。
MeterTiming(测量定时)元类是定义来测量被测量方法执行所需的时间量的。MeterTiming(测量定时)元类定义了下列方法:sommBeforeMethod()(SOMM前处理方法);sommAfterMethod()(SOMM后处理方法);StartTimer()(启动定时器)和StopTimer()(停止定时器)。sommBeforeMethod()方法在客户方法执行之前被调用,并调用内部方法StartTimer()来启动定时器。然后这个方法被执行,然后调用sommAfterMethod(),后者又调用内部方法StopTimer()来停止定时器。然后,定时器便含有执行客户方法所需的有效时间。
图13举例说明的元类和方法代表适用的BeforeAfter元类(图11的)。本专业的技术人员会看到,在最佳实施例中定义的这些元类只是利用框架可以实现的许多不同类型测量功能的一些例子而已。为了定义需要完成的其他类型的测量,或许还要再定义另外一些元类。
图14举例说明属于最佳实施例中的Principals种类(来自SOM工具箱种类的两个SOM类除外)的适当的类。MeteredEntity(被测实体)是一种可扩展的抽象类。被测量的对象必须是来自MeteredEntity类的子类。MeteredSuite(被测组)类是代表一组MeteredEntity对象的类,这些对象由与MeteredEntity类有着”has by value”(“按值具有”)的关系的MeteredSuite类代表,具有类关系上的”n”,后者表示MeteredSuite可能含有许多不同的被测实体。MeteredSuite的被测数据是它所含的被测量的Entity(实体)的和。组(suite)的概念使诸如当框架机制被调用时等情况下测量一组对象的使用人数变得容易。MeteredSuite定义了addMeteredEntity()(附加被测实体)方法,getMeteredEntities()(获得被测实体)方法和removeMeteredEntity()(去除被测实体)方法。addMeteredEntity()方法把一个MeteredEntity(被测实体)加入这个MeteredSuite(被测组)中。getMeteredEntities()方法再现这种MeteredSuite 的 MeteredEntity(被测实体)的集合。而removeMeteredEntity()方法从这种MeteredSuite中去掉特定的MeteredEntity(被测实体)。
Principal(主角)是一种抽象的类,它在框架中为Principals(各主角)定义行为。Principals是这样的一些对象,他们不是使用MeteredEntity(被测实体),就是与后者有关。特定类型的Principal(主角)是Principals(各主角)类的子类,诸如图14举例说明的最佳实施例的Program(程序)类、Location(位置)类和User(用户)类。Principal定义setName()(设置名字)方法、isVIP()(是非常重要角色)方法和getName()(获得名字)方法。setName()方法把作为参数传递的输入串设置为Princpal的名字。isVIP()方法用来确定对象是否一个非常重要的Principal(Very Important Principal-VIP),并若是VIP则返回真,否则返回假。getName()方法用来确定并返回Principal对象的名字。请注意,MeteredSuite类和Principal类都是来自SOMPPersistentObject类的子类,以便利用它预先定义好的提供持久性的方法。
Program(程序)、Location(位置)、User(用户)和VIPUser(非常重要主角用户)类是(自图11的)SpecificPrincipals(特殊主角)类的一些例子。Program(程序)类是代表可执行程序的Principal(主角)。Program(程序)类定义了execute()方法和new()方法。execute()方法执行与Principal(主角)对象有关的计算机程序。new()方法通过传递程序名来调用,它使与这个程序名对应的程序被实例化。
Location(位置)类代表诸如网络上的计算机工作站(亦即,结点)等被测数据实际存在的位置。Location(位置)定义了new()方法,后者用来在new()方法被调用时用作为变元传送过来的名字建立新对象。
User(用户)类代表使用MeteredEntity(被测实体)或与之交互作用的用户(人)。User(用户)对象是为需要监视的用户而建立的。User(用户)类定义一种new()方法,后者用来在new()方法被调用时用作为参数传送过来的名字建立新的User(用户)对象。
正如图14举例说明的,最佳实施例还包括VIPUser(非常重要主角用户)类,后者是User(用户)和VIP(非常重要主角)类的子类。VIP(非常重要主角)类只定义了一个isVIP()方法,若User(用户)是VIP(非常重要主角),它返回真,否则返回假。由于VIP类是一个VIP,所以对于这一个类isVIP()总返回真。VIP是非常重要的主角。VIP类是这样定义的,使得这一类的对象享有特殊的优先权。例如,具有VIP状态的对象即使一对象已经达到了某种限度,也还可以不被禁止访问所述对象。VIP的子类必须使用正确的类的优先顺序,以保证所述子类的isVIP()方法被调用。否则,所述对象将不会享有VIP状态。
Metered Data(被测量的数据)种类中的类示于图15类示意图,包括MeteredData(被测数据)类、MeteredEntityData(被测实体数据)类、MeteredUsageData(被测使用人数数据)类、MeteredConcurrentUsageData(被测并行使用人数数据)类、MeteredUserData(被测用户数据)、MeteredLocationData(被测位置数据)类和MeteredTiming(被测定时)类。MeteredDara(被测数据)类和MeteredEntityData(被测实体数据)类都是SOMPPersistenetObject(SOM持久性对象)类的子类,以利用它预先定义好的提供持久性的方法。MeteredData(被测数据)类正如用从MeteredData(被测数据)到MeteredEntityData(被测实体数据)的”has by reference”(“按引用具有”)的关系所表达的,是一个或多个MeteredEntityData(被测实体数据)对象的集合。MeteredData(被测数据)定义了两种方法。第一种是getMeteredEntityDataCollection()(获得被测实体数据集合),它返回MeteredEntityData(被测实体数据)对象的集合。第二种是getMeteredEntityData()(获得被测实体数据),它用来访问作为参数传递过来的对象名字用的MeteredEntityData(被测实体数据)。
MeteredEntityData(被测实体数据)类包含所述类用的全部被测量的数据。MeteredEntityData定义了两种方法,clearData()(清除数据)和getData()(获得数据)。getData()方法用来返回与输入参数所规定的类有关的数据。不同类型的MeteredEntityData是通过适当地建立子类而定义的。正如图15举例说明的,在最佳实施例中,MeteredUsageData(被测使用人数数据)类、MeteredConcurrentUsageData(被测并行使用人数数据)类、MeteredUserData(被测用户数据)类、MeteredLocationData(被测位置数据)类和MeteredTiming(被测定时)类定义了可能需要储存的不同类型的被测数据。这些类中的每一个都代表了图11所示的SpecificMeteredEntityData(特殊被测实体数据)类。
MeteredUsageData(被测使用人数数据)类收集Metered Entity(被测实体)用的使用人数数据,并包括两个方法,incrementMethodInvocation()(增量方法调用)和incrementMethodInvocationData()(增量方法调用数据)。incrementMethodInvocation()方法被调用来使被测对象的使用人数加一。而incrementMethodInvocation()方法又调用内部方法incrementMethodInvocationData(),后者实际地使作为参数传递的类和方法的名字所规定的方法用的使用人数计数加一。MeteredConcurrentUsageData(被测并行使用人数数据)类收集MeteredEntity(被测实体)用的并行使用人数数据。这是标准使用人数测量的专门化。它不是简单地每次访问的使用人数数据加一,而是所述数据必须在每次访问开始时加一,同时必须在所述方法执行完成时减一。除了通过建立子类来定义的方法之外,MeteredConcurrentUsageData(被测并行使用人数数据)还定义了方法decrementMethodInvocation()(减量方法调用)和decrementMethodInvocationData()(减量方法调用数据)。decrementMethodInvocation()方法调用来在所述方法执行完成时减一,并调用内部方法decrementMethodInvocationData()来完成这一操作。
MeteredUserData(被测用户数据)类收集关于与MeteredEntity(被测实体)相联系的用户(人)的数据。在这个类上定义了两种方法。当方法incrementUserAccess()(增量用户访问)被调用时,内部方法incrementUserAccessData()即被调用,使与客户方法的类对应的用户访问(次数)加一。
MeteredLocationData(被测位置数据)类储存与特定的MeteredEntity(被测实体)相联系的位置,并定义了三种方法:changeLocation()(改变位置),storeLocation()(存储位置)和storeLocationData()(存储位置数据)。changeLocation()方法被调用来改变与特定的被测实体相联系的现存位置。在changeLocation()被调用时,传递两个参数:Class(类)名和Location(位置)对象。于是所述类的位置便被改变到新的位置上。storeLocation()方法把一个Location(位置)对象分配给特定的类名,其中Class(类)和Location(位置)是作为参数传递过去的。这两个方法都调用内部方法storeLocationData()来储存与被测实体相联系的Location(位置)。
在图15中讨论的最后一个类是MeteredTiming(被测定时)类,它将Metered Entity(被测实体)用的定时信息作为各个时间项的集合储存起来。由MeteredTimingData(被测定时数据)类定义的方法包括:addTimingEntry()(附加定时实体),addTimingEntryData()(附加定时实体数据)和getData()(获得数据)。addTimingEntry()方法通过调用内部方法addTimingEntryData()增加作为参数传递过来的类名和方法名的定时项。getData()再现作为参数传递过来的类的时间项的集合。
请注意,在最佳实施例中,MeteredEntityData(被测实体数据)的子类数目与Metering(测量)种类(图13)中的元类数目相同,而每一个元类都有一个对应的MeteredEntityData类。这样做是有意义的,因为必须为要完成的每一种类型的测量定义测量数据。
现参照图16,作为Configuration(配置)种类成员的类包括ConfigurationData(配置数据)类、MeteredEntityConfiguration(被测实体配置)类和MeteredMethod(被测方法)类。如图所示,图16的其他类来自其他种类。ConfigurationData(配置数据)类正如与MeteredEntityConfiguration(被测实体配置)类的”has by reference”(按引用具有)关系所表明的,它是MeteredEntityConfiguration(被测实体配置)对象的集合。ConfigurationData(配置数据)类定义了几种方法,包括:addEntityConfiguration()(附加实体配置),getMeteredEntityConfiguration()(获得被测实体配置) ,removeMeteredEntityConfiguration()(去除被测实体配置),getCentralLocation()(获得中心位置)和setCentralLocation()(设置中心位置)。addEntityConfiguration()方法用来为待测量的新对象增加配置。输入参数定义所述被测类的名字。getMeteredEntityConfiguration()方法再现作为参数传递的类的MeteredEntityConfiguration(被测实体配置)对象。removeMeteredEntityConfiguration()方法去除作为输入参数传递的类名的配置信息。所述方法与addEntityConfiguration()方法是互补的方法,一个为类增加配置信息,而另一个去除类的配置信息。getCentralLocation()方法返回所有的被测对象的被测数据在网络上的结点位置。为了同步地更新网络上的被测数据,必须掌握全部被测数据的中心位置。setCentralLocation()方法检索作为参数传递的结点识别符,并将被测数据的中心位置设置在所述结点上。
MeteredEntityConfiguration(被测实体配置)类为每一个要测量的对象定义配置对象。每一个MeteredEntityConfiguration对象都含有对应被测对象的全部配置,包括:所述对象是否属于一个组(suite);任何在某种测量条件出现时为了完成某种功能所必需的可用阈值;以及所述对象是否处于同步方式。下面将讨论这些配置选项。
对于图16举例说明的最佳实施例我们要考虑的第一个类型的配置数据涉及所述对象是否属于一个组。若几个对象全都以特定的方式相互联系,则定义为一组对象。组的一个例子是面向对象的框架机制。框架中的全部对象都可以作为一个组的成员列出,以至对一个组中的一个对象的访问的测量就和对作为所述组成员的所有对象的访问相同。在最佳实施例中定义了几种有关组的方法。第一种是addTosuite()(附加到组),它将客户对象加到作为参数传递的组中。另一种方法是clearSuites()(清除组),它用来从这个对象的配置数据中清除所有的组。getSuites()(获得组)方法用来返回包括对应于配置数据的被测对象的所有的组的集合。而removeFromSuites()方法(从各组中去除)用来从配置数据中清除作为参数传递过来的组。
第二种类型的配置数据涉及要求框架采取某种行动的适当阈值。适当的阈值例子涉及并行使用用户数,而如果这个数目超过了阈值(对应于许可证协议允许的并行使用的用户数),则框架采取适当行动,诸如提示用户或系统管理员已经超出用户数限度。定义了几种涉及阈值的方法。addThreshold()(附加阈值)方法把作为参数传递的阈值对象加到配置数据上。clearThresholds()(清除阈值)方法用来从配置数据清除全部阈值。getThresholds()(获得阈值)方法返回与这个配置数据对应的被测对象用的阈值对象的集合。而removeThreshold()(去除阈值)方法用来从配置数据中去除作为参数传递的阈值。
另一种类型的配置数据涉及对应于MeteredEntityConfiguration(被测实体配置)对象的被测对象是否是处于同步方式。若被测数据需要从中心位置收集,则它便处于同步方式。若被测数据可以在不同的位置收集,并与后者相关,则它便处于异步方式。isSynchronousMode()(是同步方式吗?)方法用来确定被测数据是否处于同步方式。若是假,则处于异步方式。setSynchronousMode()(设置同步方式)方法用来为这个配置设置收集方式,其中真指出同步方式,而假指出异步方式。
MeteredEntityConfiguration(被测实体配置)类也定义了一种clearAll()(全部清除)方法,它用来从与被测对象对应的MeteredEntityConfiguration对象清除全部配置数据。请注意,MeteredEntityConfiguration类与MeteredEntity(被测实体)类、MeteredSuite(被测组)类和Threshold(阈值)类有着使用关系,因为MeteredEntityConfiguration(被测实体配置)中的各种方法可能需要调用关于这些其他类的方法。
MeteredMethods(被测方法)类是MeteredEntityConfiguration(被测实体配置)的子类,并且,如图11所示,对应于适当的SpecificMeteredEntityConfiguration(特殊被测实体配置)类。具体地说,MeteredMethods用来存储这些在方法层次上被测量的类的配置信息。这样的类的例子是Metered Usage(被测使用人数)。除了MeteredEntityConfiguration(被测实体配置)中定义的方法以外,MeteredMethods(被测量方法)也定义其他与哪一个方法是准备测量的有关的方法。addMethodToInclude()(附加包含的方法)方法把作为参数输入的方法作为测量这个配置的方法加入。clearMethodsToInclude()(清除包含的方法)方法清除欲测方法的全部配置信息。而getMethodsToInclude()(获得包含的方法)方法返回在这个配置中被测方法的集合。
现参见图17,属于Thresholds(阈值)种类的类包括Threshold(阈值)类、CumulativeAccesssThreshold(累计访问阈值)类和ConcurrentAccessThreshold(并行访问阈值)类。Threshold(阈值)是SOMPPersistentObject(SOM持久性对象)的子类,并使用Program(程序)类。Threshold(阈值)类定义要监视的事件、可用限度和超过所述限度时发出通知用的程序。Threshold(阈值)类提供与上列功能有关的方法。例如,decrementUsage()(减少使用人数)方法将当前限度设定减一,而incrementUsage()(增加使用人数)方法将当前限度设定加一。内部方法getLimit()(获得极限值)返回与这个阈值有关的当前限度。内部方法getProgram()(获得程序)返回与这个阈值有关的而当这个阈值的限度被超过时预定要运行的Program Principal(程序主角)。setLimit()(设置极限值)方法为这个阈值设定阈值限度。而setProgram()(设置程序)方法把作为参数传递的程序设置为当所述限度被超过时要调用的程序。
CumulativeAccesssThreshold(累计访问阈值)类和ConcurrentAccessThreshold(并行访问阈值)类都是Threshold(阈值)类的子类,并为它们专门的功能定义了另外一些方法。例如,设置总的累计访问的CumulativeAccesssThreshold(累计访问阈值)类包括decrementUsage()方法和new()方法。因为类的累计访问阈值将随着时间增大,所以,在这个子类中的decrementUsage()方法将只是被超越,使得incrementUsage()方法增加所述极限值,而decrementUsage()方法并不进行典型的减一,结果得出累计访问阈值的值。new()方法返回当new()被调用时被实例化的新的CumulativeAccesssThreshold(累计访问阈值)对象。类似地,ConcurrentAccesssThreshold类上的new()方法返回当new()被调用时被实例化的新的ConcurrentAccesssThreshold(并行访问阈值)对象。这样,阈值可以根据需要定义。
核心功能
图11能够最好地把本发明的对象测量框架中的核心功能和可扩展功能区分开。尤其是,正如上面指出的,MeteredData(被测数据)类、ConfigurationData(配置数据)类和MeteredEntityConfiguration(被测实体配置)类是核心类,而其余的类是可扩展的类。图11所示的全部类的关系都是核心关系,并且不能由框架的用户改变。事实上,这是表示框架特征的类之间的这些关系的固定的特性,并使之变得有用和功能强大。对象测量框架的核心功能是由核心类、核心类关系以及导致所述框架以要求的方式行事的功能要求确定的。正如上面就图9描述的,对象测量框架的整个核心功能包括方法900的各步骤。构成任何一种测量环境的特定步骤取决于框架的用户如何扩展这些类以及如何定义(或超越)适当的方法。
扩展对象测量框架的实例
为了理解程序员如何利用本发明的对象测量框架,下面描述几个例子。图11举例说明程序员如何从MeteredEntity(被测实体)类给待测量的对象建立子类,并将其分配给适当的BeforeAfter(前、后处理)元类来完成要求的测量功能。对于最佳实施例,适当地建立子类并分配给元类的特定的实例示于图18。若程序员想测量被测对象的用户,就会从MeteredEntity(被测实体)类建立UserExample(用户实例)类作为子类,而其元类是MeterUsers(测量用户)元类。若程序员想测量被测方法的执行时间,就会从MeteredEntity(被测实体)类建立TimingExample(定时实例)类作为子类,而其元类是MeterTiming(测量定时)元类。若程序员想测量被测对象的储存位置,就会从MeteredEntity(被测实体)类建立LocationExample(位置实例)类作为子类,而其元类是MeterLocation(测量位置)元类。若程序员想测量对象的使用人数,就会从MeteredEntity(被测实体)类建立UsageExample(使用人数实例)类作为子类,而其元类是MeterUsage(测量使用人数)元类。另外,若要进行比较复杂的测量。既测量被测对象的使用人数又测量其位置,则程序员建立UsageAndLocationExample(使用人数和位置实例)类作为子类,而其元类是MeterUsage(测量使用人数)元类和MeterLocation(测量位置)元类。从上例我们可以看出,若程序员想测量特定的属性,他必须定义Metering(测量)种类中适当的元类,然后必须从MeteredEntity(被测实体)类建立被测对象子类,并选择对应的元类。下面将参照图19至24的对象示意图,讨论图18的例子的对象测量框架的操作。
对象相互作用
图18中的UsageExample(使用人数实例)用的对象示意图示于图19。ClientProgram(客户程序)对象通过调用作为被测对象的UsageExample上的someMethod()(步骤1)来调用对象测量框架。这种测量方法便被执行(步骤2)。所述方法执行之后,或者与之并行,进行包括在步骤3-12的测量功能。关于MeterUsage(测量使用人数)对象的sommAfterMethod()(SOMM后处理方法)被调用(步骤3),将所有必须在所述方法执行(在步骤2中)之后完成的功能踢开(kick off),来完成要求的使用人数测量。MeterUsage(测量使用人数)对象调用关于MeteredData(被测数据)对象的getMeteredEntityCollection()(获得被测实体集合)方法(步骤4),后者返回与Metered Entity(被测实体)(在这种情况下被测对象和/或方法)对应的对象的集合。一旦MeterUsage(测量使用人数)对象有了Metered Entity(被测实体)的集合,它便调用关于UsageExample(使用人数实例)对象的somGetClassName()(获得类名字)方法(步骤5),后者返回在步骤1上其客户方法调用的类的名字。接着,把所述类名和在步骤1调用的方法的方法名作为参数传递,调用incrementMethodInvocation()(增量方法调用)方法(步骤6)。为了知道如何使方法调用(数)加一,首先必须传递要求的被测实体的配置的类的名字并调用getMeteredEntityConfiguration()(获得被测配置)方法(步骤7),来确定配置。这种方法将MeteredMethods(被测方法)标示为可用配置类。接着,MeteredUsageData(被测使用人数数据)对象调用关于MeteredMethods(被测方法)对象的getSuite()(获得组)方法(步骤8)、getThresholds()(获得阈值)方法(步骤9)、getMethodsToInclude()(获得包含的方法)方法(步骤10)和isSynchronousMode()(是同步方式吗?)方法(步骤11),来确定与在步骤1上调用的方法有关的配置。一旦知道了配置,MeteredUsageData(被测量使用人数数据)调用它自己的incrementMethodInvocationData()(增量方法调用数据)方法,来适当地使方法调用(数)数据加一。例如,若UsageExample(使用人数实例)对象是一个组的一部分,则这个方法会使所述组中的所有对象的方法调用数据都加一,而不仅仅是为在步骤1上被调用的客户方法加一。
图20表示图18的UserExample(用户实例)用的对象示意图。所述框架再一次通过ClientProgram(客户程序)调用作为关于UserExample(用户实例)(它是通过建立适当的子类而为测量选择的对象)的方法的someMethod()(某种方法)(步骤1)而被调用。UserExample(用户实例)对象调用someMethod()(某种方法)方法,后者执行客户程序所请求的方法。不是在someMethod()方法执行之后(在单线程系统中),就是与之并行(在多线程系统中),所述框架就会完成步骤3-14所代表的测量功能。UserExample(用户实例)调用MeterUsers(测量用户)对象上的sommAferMethod()(SOMM后处理方法)(步骤3),来开始测量功能。然后,MeterUser(测量用户)调用它自己的getUserName()(获得用户名字)方法,后者返回在步骤1上调用someMethod()的用户(人)的名字。然后,通过调用构造符方法new()(步骤5),建立所述用户用的User(用户)对象。接着,调用关于MeteredData(被测量数据)对象的getMeteredEntityDataCollection()(获得被测实体数据集合)方法返回被测量数据的集合(步骤6)。然后,MeterUsets(各测量用户)调用关于UserExample(用户实例)对象的somGetClassName()(som获得类名字)方法(步骤7),后者返回在步骤1被调用了的客户方法的类的名字。接着,incrementUserAccess()方法被调用(步骤8),来指令MeteredUserData(被测量用户数据)对象,后者是更新表示所述用户访问所述方法多少次的计数所必需的。属于所述方法的类(步骤7)和所述用户作为参数传递。但是,在MeteredUserData(被测用户数据)能够更新配置数据,以反映对所述方法的新的访问次数之前,它首先必须调用关于ConfigurationData(配置数据)对象的getMeteredEntityCollection()(获得被测实体集合)方法(步骤9)来确定哪一个配置数据属于在步骤1上被调用的方法。这一方法返回与在步骤1被调用的客户方法对应的MeteredEntityConfiguration(被测量实体数据)对象。然后,MeteredUserData(被测量用户数据)对象通过调用关于MeteredEntityConfiguration(被测实体数据)对象的getSuite()方法(步骤10)、getThresholds()方法(步骤11)和isSynchronousMode()方法(步骤12),来确定配置,并通过调用它自己的incrementUserAccessData()方法(步骤13)来适当地使用户访问计数加一。
回顾图19和20的对象示意图,看来正在开发出一种框架如何在不同的测量环境下完成需要的测量功能的范例。图21的对象示意图表示图18的LocationExample(位置实例)用的对象的相互作用。所述框架再一次由ClientProgram(客户程序)调用,调用关于LocationExample(位置实例)的someMethod()方法(步骤1),并执行所述方法(步骤2)。步骤3开始测量功能,步骤4确定LocationExample(位置实例)(被测对象)的位置,而步骤5建立新的Location(位置)对象。步骤6为所有的被测实体检索数据集合,而步骤7检索LocationExample(位置实例)在其下被实例化的类的类名。步骤8传递从步骤7得到的类名和Location(位置),告诉MeteredLocationData(被测位置数据)把数据存于何处。步骤9返回持有在步骤1被调用的方法的MeteredEntityConfiguration(被测实体配置)对象,然后,MeteredLocationData(被测位置数据)通过完成步骤10-12确定配置。然后,MeteredLocationData(被测位置数据)在步骤13被更新,而步骤14检索Location(位置)对象的名字。
图18的TimingExample(定时实例)的对象示意图示于图22。这里,对象的相互作用与以前讨论过的那些例子略有不同,因为框架必须在使所述方法被允许执行之前启动定时器,并在所述方法执行之后停止定时器。ClientProgram(客户程序)按步骤1调用someMethod()。步骤2调用关于MeterTiming(测量定时)对象的sommBeforeMethod()(SOMM前处理方法)方法,后者使它在步骤3调用getMeteredEntityDataCollection()(获得被测实体数据集合),后者返回被测实体数据的集合。然后,MeterTiming(测量定时)在步骤4调用startTimer(),然后TimingExample(定时实例)进行步骤5,执行在步骤1调用的方法。所述方法被执行之后,在步骤6调用sommAfterMethod()(somm后处理方法),结果在步骤7调用stopTimer)方法。然后,在步骤8利用somGetClassName()(som获得类名字)方法发现TimingExample(定时实例)对象的类。在步骤9,通过调用addTimingEntry()(附加定时实体)方法并将在步骤8发现的类和步骤1调用的方法,以及储存在MeterTimimg(测量时间)中的时间作为参数传递,把在步骤5上执行someMethod()方法用的时间加到MeteredTimingData(被测定时数据)上。MeteredTimingData(被测定时数据)首先必须通过完成步骤10确定哪一个MeteredEntityConfiguration(被测实体配置)适用于在步骤1被调用的方法。然后MeteredTimingData(被测定时数据)对MeteredEntityConfiguration(被测实体配置)完成步骤11-13,并完成步骤14来适当地添加定时项。
图18的UsageExample(使用人数实例)用的对象示意图示于图23。在步骤1ClientProgram(客户程序)调用someMethod(),后者在步骤2被执行。步骤3把框架的测量功能踢开。步骤4返回MeteredEntityData(被测实体数据)的集合。步骤5返回UsageExample(使用人数实例)所属的类。步骤6指令MeteredEntityData(被测实体数据)把关于在步骤1被调用的方法的方法调用(次数)加一,但是,MeteredEntityData(被测实体数据)首先必须在步骤7确定哪一个MeteredMethods(被测方法)对象适用于在步骤1调用的客户方法。这种方法返回图23的MeteredMethods(被测方法)对象。然后,MeteredEntityData(被测实体数据)在步骤8-11确定配置。我们在这里假定,在步骤11is SynchronousMode()返回真,这要求MeteredEntityData(被测实体数据)在步骤12确定中心位置,并在步骤13改变中心位置上的MeteredUsageData(被测使用人数数据)(亦即中心处的MeteredUsageData)。
与图18的UsageAndLocationExample(使用人数和位置实例)对应的对象示意图示于图24。这个对象示意图描绘同时测量使用人数和位置的全部步骤(1-27)。仔细考察与UsageExample(使用人数实例)(图19)和LocationExample(位置实例)(图21)相关的对象示意图就会理解每一步的细节。图24的对象示意图举例说明所述框架可以用来一次监视多个特性。
正如最佳实施例举例说明的,所述框架通过简单地定义实现特定测量环境所特有的特征的对象,就提供了用来实现许多不同的对象测量环境的极其灵活而又功能强大的工具。尽管最佳实施例是联系图12-17来描述的,并提供一些特定子类建立方法,但是所述框架在其最广泛的意义上还是呈现在图11上。还应该指出,并非图11上所有的特征都是严格地必需的,这取决于欲进行的测量的类型和复杂程度。例如,若仅仅为了记录和报告计算机程序中对象的使用人数而进行测量,则将Thresholds(阈值)类删除,图11的框架就能适当地完成其任务。在本发明的范围内,可以对本发明的对象测量框架作各种各样的修改。
这里提出的实施例和实例都是为了更好地理解本发明及其实际应用,从而使本专业的技术人员能够实现和利用本发明而提出的。但是,本专业的技术人员会认识到,上面的描述和实例都仅仅为举例说明而提出的。提出的描述并非意在穷举或将本发明限制在所公开的准确的形式上。在不离开后附权利要求书的精神和范围的情况下,在上述教导下,可以作出许多修改和改变。
符号表示法
在面向对象编程思想的交流上,目前尚无普遍接受的符号表示法。本说明书采用的符号表示法非常类似于Grady Booch先生提出的编程业所熟知的Booch符号表示法。Booch先生是Benjamin/Cumings Publishing Company,Inc公司出版的Object-orientedAnalysis and Design With Application一书,第二版(1994)的作者。在本说明书中使用Booch符号表示法不应暗示在本发明者和/或本发明申请书的受让人与Booch先生或Booch先生的雇员之间有任何联系。对于Booch先生使用的符号表示法系统,在上列书的第7章171-228页有比较充分的解释。下面将一般地解释这里使用的符号表示法系统。
一种由面向对象的框架建立模型的系统可以用被称为顶层类示意图的示意图高层次抽象地呈现出来。附图中的图1是顶层类示意图的一个例子,它含有表示所述模型系统的抽象的方框。这些方框安排成层次结构,使得代表接近系统物理组件的抽象的方框处在示意图中较低的层次上,而代表比较抽象的功能性的组件的方框则处于示意图接近顶层的位置。在图1中,标有”机制”标志的方框表示包括实现模型系统组件的装置的抽象。方框(机制)可以设想成包括多个按照面向对象的编程概念定义的类似的类的种类。图1代表一种动物园管理模型,因而层次较低的方框包括:被称为Animal Mechanism(动物机制)的方框,它代表动物园模型中的动物;被称为Containment UnitMechanism(禁闭装置机制)的方框,它代表动物的围栏和笼子。在图1的最高层次上,被称为Zoo Administration(动物园管理)的方框表示一种包括了由人员完成的各种各样管理任务的功能抽象。
顶层类示意图中的方框代表提供系统行为的系统抽象。系统抽象包括类和对象。系统类的细节在类示意图中提供,后者用来表示类的种类,并表示这些类的的关系和责任。类用一个形状不规则的虚线画的一般被称作云标的图标代表。例如,图2示出表示为云标的几个类。每一个类由一个对于相关的类的种类而言是唯一的名字识别,并指出每一个类对于图1举例说明的机制中的一个的关系。在类的图标中,类名列在属性名、后跟括号的操作名和括在括号内的限制的上面。图3比较详细地举例说明Zoo Administrator(动物园管理员)类。图3指出Zoo Administrator(动物园管理员)类包括多个操作,包括一些被称为”5_minute_timer()”、”ad_animal()”和”add_containment_unit()”操作。操作名(和类属性名)中的字用一个下划符分开,以便阅读。类属性清单的一个示例是在图5中举例说明的Animals(动物)类中的被称为”feed_freq”(喂食频繁程度)和”temp_range”(温度范围)的属性。
机制(图1)和类(图2)之间的连线表示这样一些个别的抽象之间的关系。这样,图1方框的连线代表不同机制之间的关系。例如直的连线代表简单的相关的关系,表示共享的信息。”using”(使用)关系是简单相关的细化(refinement),以此表示被称为服务者或供应者的一种抽象向另一种被称为客户的抽象提供服务。这样的关系用简单的相关线一端的开口圆圈表示,开口圆圈一端标出”使用”相关服务者的客户。
两个类之间简单相关的另一种细化是被称作继承关系的类型。继承是一个类共享与一个或多个类相关的结构和/或行为的类之间的关系。继承相关亦被称作”is”(是)的关系。这样,给定A和B两类,若A是B的一个实例,则A类具有与B类的继承关系;A被说成是B的子类,而B被说成是A的超类或父类。就是说,A”is a”(是一个)B。继承关系用一端有箭头的连线表示,指出从连线另一端的父类衍生出其特性的子类。
类关系的另一个细化被称作聚合(aggregation)关系,它表示整体与其部分或属性类之间的关系。在符号表示法中,在用相关线连接的整体类和属性类之间,聚合关系用实线园表示,一端是整体类,另一端是属性类。
类示意图规定的另一种关系是实例化(instantiation)关系。实例化关系代表诸如由编程语言支持的类的具体实施的类的实例。例如,被称为”animals”(动物)的类可以有许多实例,包括狮子、老虎和熊。一个类的实例用有一个箭头的相关虚线表示,从一个类的实例指向所述一般的类。最后,被称为元类的类关系表示这样的关系,其中一个类本身被作为可以处理的对象看待。也就是说,元类是一种其实例就是所述类本身的类。诸如Siall Talk等某些计算机语言支持元类的概念。这样的关系用带有一个从元类的一个实例指向所述一般类的箭头的阴影线表示。
类可以参数化,这表示其结构和行为独立于其格式类参数而定义的一族类。参数化类用云形类标和云标一部分上面放一个矩形框标示。参数清单在矩形框中列出。实例化的类包括参数框,被称为修饰(adornment),而不是一般类所用的虚线框。参数化类与其实例化的类之间的的参数化关系用指向参数化类的虚线标示。一般说来,一个实例化的类要求对另一个用作实参数的具体的类有”using”(使用)关系。
类的属性可以用包括在类的云标内的类修饰来代表。具体地说,抽象类用云标中的三角形内的大写”A”的块标示。抽象类是一种不会建立实例的类。就是说,它是具有多个类的类。其他类修饰是面向对象的实施语言的功能。例如, C++语言允许特殊的类限制条件(qualification),后者在特定的修饰(adornment)中给出。静态类用修饰三角形内的大写”S”块标示,友类用修饰三角形内的大写”F”块标示,而虚拟类用修饰三角形内的大写”V”标示。
除了定义类以外,面向对象系统的设计者还必须定义对象(见Booch书中的136页)。对象用实线云标标示,其中放入对象名,放在对象属性清单的上面。对象是实在的实体,它表现出完全确定的行为。对象是用来代表由面向对象的程序表达的实际系统的某一部分。对象用状态、行为和标志(identity)来表征。可以反对象想象为类的实例。对象的行为是所述对象如何表现、其状态变化时作何反应的表示和它的传递信息的动作。
对象及其相互关系在对象示意图中表示,后者包括对象图标,后者又具有指出对象之间同步的链接。链接标有顺序的数字,表示操作的流程。两个对象之间链接的存在指明它们的对应的类之间的相关,并表示它们之间的通讯路径。这样,两个对象之间的链接表示一个对象可以向另一个对象发送信息。信息传递的方向用从启用一种操作的被称为客户的对象指向提供所述操作的被称为供应者的对象的箭头装饰的简单的连线表示。这样一种简单的同步关系的表示方法表明传递信息的最简单的形式。这样的相关关系可以指出,例如,一种操作的启用。操作参数可以在链接线旁边指出。
某些对象是主动的,意味着它们体现它们自己的控制线程。就是说,这样的对象不是简单地顺序(执行的)(sequential)。主动对象具有各种不同的并行特性。若对象具有多个控制线程,则必须规定同步。信息同步化可以是同步的,意味着客户将等待直至提供者接收信息为止。同步的同步化用带箭头的”X”标示。同步化可以包括妨碍(balking)信息传递,意味着若提供者不能立即提供(service)信息,则客户将放弃所述信息。妨碍(balking)用返回本身的箭头标示。同步化可以包括超时同步,这意味着若提供者不能在规定的时间内提供(service)信息,客户就放弃信息。超时同步用链接箭头旁边的钟面标示。最后,同步化可以包括同步信息,意味着客户向供应者传送一个事件要求处理,供应者把所述信息放入队列,然后客户不再等待供应者而继续前进。本专业的技术人员都会看出,异步信息同步化类似于中断处理。异步信息同步化用半个箭头标示。
Booch符号表示法包括跟踪对象和类的执行的相互作用示意图是有意义的。相互作用示意图是进行了根本改造的对象示意图。就是说,相互作用示意图传递与对象示意图传递的相同的信息,但是仅仅以不同的格式表现相同的信息。本说明书利用对象示意图,但是,本专业的技术人员都会认识到,对象示意图和相互作用示意图是等价的,而且不作进一步的解释也会理解,如何从一个转换到另一个。
例如,在图7,被称为Zelda的对象705通过调用称为ListZooKeeper(列出动物园饲养员清单)的操作,从被称为Zoo KeeperRegister(动物园饲养员登记)的对象处获得当前动物园饲养员清单。第二步处理在图7中用Zoo Keeper Register(动物园饲养员登记)对象代表,通过操作调用,向Zelda对象传递包含动物园饲养员清单的信息。动物园饲养员对象包括称为Tina,Vince和Fred的Zoo Keeper(动物园饲养员)类的成员。对象示意图中指出的第三步是对象Zelda向每一个动物园饲养员传递信息,指令他们通过调用每一个动物园饲养员对象各自的Check Animals(检查动物)操作来检查动物。