技术开发 频道

面向对象技术在软件重用和体系结构中的应用

    以数据为中心的系统模型如图2a所示。这类模型将数据库放在系统的核心层次共享,各功能部件采用统一的数据描述,各子系统的开发过程完全独立;子系统间有统一的数据交换接口;整体的可扩充性好,可任意增加符合数据交换标准的应用程序。但是,这种模型整体结构松散,集成性不够良好;只能做到数据复用,不能做到功能复用,造成大量的代码冗余;由于应用相关数据的存在,难于定义符合所有应用需求的数据接口标准,因此会出现数据语义失真。从开放性的角度来讲,这类系统只具有数据开放性,不具有功能开放性,但其可扩充性很好。

    以执行为中心的系统模型着眼于将不同的应用系统通过统一的执行中心来实现数据和用户界面的共享和一致,如图2b所示。这类模型将共有的计算和执行功能从应用程序中分离出来,放在执行中心,避免了代码冗余;用户与系统的交互与应用程序相分离,便于实现统一风格的用户界面;和数据库的任何数据交换都要通过执行中心进行,有利于数据的严格管理,保证了数据的一致性。这类模型解决了以数据为中心的系统模型的代码冗余及界面风格不统一等问题,但仍存在一些缺陷:执行中心的功能设计复杂,很难确切定义符合所有应用要求的功能集合,而且实现起来也相当困难;执行中心同时与用户界面和所有应用程序保持通讯,又管理着数据,负担过重,容易形成瓶颈。总之,这类模型既具有数据的开放性,又具有功能的开放性,可扩充性也好,整体上优于以数据为中心的系统模型。

    随着面向对象技术的成熟,出现了更为简炼的面向对象的系统模型,与前两类模型的设计思想有较大差别,如图2c所示。其中,系统内核对象中封装的是能为用户界面对象和所有应用对象所共享的数据及相应的操作;用户界面对象中封装的是用户界面数据及相应的操作;应用对象中封装的是应用数据及相应的操作。所有这些对象通过相互间的通讯协调来完成指定的功能。从系统构成的角度来说,这类模型的结构是无中心的,系统由各对象实体构成,各对象实体具有平等的地位,这与以数据为中心和以执行为中心的模型不同。面向对象的系统模型的主要优点在于,数据和功能的合理封装降低了由于数据和功能的集中管理所带来的通讯上的开销和操作上的复杂性;另外,系统的无中心结构也使系统的构成变得更加灵活。从整体上看,面向对象的系统模型无论其开放性还是其有效性都要优于前两类模型。

    面向对象模型比以往的模型有了很大的进步,但仍有不足:对象之间的联系是一种点对点的直接联系,当系统中对象数目增加时,通讯链接数将以平方级激增;同时,为支持通讯,每个对象实体都要维护一个包含所有对象实体功能服务信息的功能服务信息库,这部分信息不但重复,而且还要保证其一致性。这些开销都损害了系统的效率。更大的问题还在于:对象的接口没有一致的标准,造成向系统中扩充对象时的随意与不规范,不利于系统的维护以及对象的复用。

    以面向对象为基础的组件和中间件技术的逐渐成熟又为应用软件系统的建模引入了新的思想,产生了基于总线的系统模型,如图2d所示。组件、中间件是继面向对象技术之后发展起来的新的软件工程技术,是面向对象技术的延伸。基于总线的系统模型仍然是一种面向对象的结构,但系统中的对象是按照规范设计的模块,这些定义良好的软件模块(组件)在系统中共存,并且充分地相互作用。按照这种结构,可以将若干组件组合起来,以建立更大和更复杂的系统。

    这种模型的关键在于一种高效的总线结构,使组件之间能以一个公共的接口互相连接,做到组件的即插即用,无缝集成。这种模型的系统中,组件间的通讯链接数是线性的,并且由于各组件接口规范的一致性,通讯的复杂度大大下降,也提高了组件的互操作性。

    根据组件在系统中地位的差异,应用软件系统中的组件可以分为两个层次:核心组件和应用组件。相对于核心组件来说,应用组件所要求的系统服务要少得多,请求服务的频度也较低。相应地,总线也可以分为核心总线和应用总线,从而形成双总线结构。在这种总线结构中,核心组件和应用组件之间仍然保持良好的互操作性,但应用总线屏蔽了应用组件的一部分服务请求,减少了核心总线上的流量,从而提高了应用软件系统核心的效率。

    核心组件与核心总线构成了应用软件系统的原型和框架,在此基础上与各应用组件集成。

    通常在分布式环境中,应用组件不是直接连结到应用总线(也称Broker)上,而是通过一个软件代理(Agent)间接地连在总线上,如图3所示。Agent的作用在于,一方面代理应用组件的复杂通讯过程,使应用组件更专注于功能的实现;另一方面将适应不同应用需求的组件内部的异构数据转换成同构数据,以保证Broker上通讯语言的统一。由此可见,在基于总线的系统模型中,Broker与Agent构成了介于应用组件(客户)与核心系统(服务器)之间的中间件。 

 

    4 并发面向对象技术

    并行计算是未来计算机的发展方向。将面向对象与并行计算的相结合的并发面向对象技术是一个比较新的研究领域,许多问题有待解决。

    目前一些流行的面向对象程序设计语言(如C++)只提供了描述程序顺序执行的能力;即使有些语言(如Smalltalk)提供了描述程序并发执行的机制,但往往采用一些传统的并发控制模式和设施,没有从对象模型本身的特点来考虑并发控制,从而造成并发与对象模型中一些概念(如封装、继承及自治等)相冲突。

    近年来,许多面向对象并发编程的方案被提出,可归纳为3种不同方法:

    1. 设计全新的并发面向对象语言;
    2. 扩展现存的顺序面向对象语言;
    3. 使用现有的顺序面向对象语言,通过外部库提供并发抽象。

    并发类库正成为并发面向对象技术中最为重要的方法。这种方法的优点是不需要修改原有顺序面向对象语言,保留原有编程方法,可以更好地利用面向对象技术中的一些特性,用户容易接受。

    为了在面向对象模型中引进并发机制,并发类库的设计必须能与对象模型中一些现有的特性有机结合,为面向对象程序设计语言扩展描述系统并发行为的能力。此外,这种方法一般还需要某种底层特殊软件(运行支撑系统)的支持,并将支撑系统的复杂性全部隐藏在类库中。

    顺序对象模型由一组被动的对象构成。系统的执行行为是,外界激活其某个对象的某个方法,该方法的执行中向系统中其他对象发送消息,从而激活这些对象的方法的执行。这里的消息发送就是过程调用,即消息发送者必须等到消息接受者的相应方法执行完毕,才能继续执行下去,整个系统只有一个执行线程(Thread)。

    在面向对象的并发模型中,可并发执行的基本单位是对象,称为并发对象。与普通对象不同的,并发对象具有自己的控制线索和独立的地址空间,多个并发对象可以并发运行,通过方法(消息传递)请求相互作用。目前存在两种构造并发对象的典型方案:

    1. 采用异步消息发送。即一个对象向另一个对象发送消息后,前者不必等待后者处理消息即可继续执行下去,后者则对消息进行缓存;

    2. 对象可以有一个体(Body),一旦对象被创建,这个体就开始执行。

    在方案1中,由异步消息发送产生新的执行线程,从而引起系统的并发。由于采用异步消息发送,必须提供今后如何取得返回值的设施。异步消息发送的不足之处在于:它使得程序的行为难以把握,不利于对程序的推理(Reasoning)。

    方案2通过创建新对象产生新的执行线程,在对象体执行的同时,对象还可以接收和发送消息,消息发送可采用同步方式,但应允许对象内部的并发,否则容易造成死锁。

    处于并发环境中的对象,随时都会面临环境对其方法的并发调用。为了保证对象状态的一致性与完整性,必须对方法的并发调用加以同步控制。同步控制可以由消息发送者执行,也可以由消息接受者执行。但是,若同步控制仅由消息发送者执行,当消息发送者由于种种原因没有进行同步控制时,将会产生对消息接受者方法的并发调用,造成消息接受者内部状态的不一致与不完整。因此,消息接受者本身必须提供同步控制。

    并发对象的同步控制可以分成两类:条件同步和互斥。条件同步是指对象在某种状态下只能接受某些消息;互斥是指当处于某种状态下的对象可以接受(处理)多个消息时,由于这些消息的处理都有可能使用对象的成员变量,如果让它们同时执行,就存在共享对象的成员变量问题,为了保证对象状态的完整性和一致性,这些方法必须互斥地使用共享变量。

    如何在并发对象类中描述对象的同步控制,一般存在两种方式:集中控制和分散控制。

    集中控制方式是把对象的同步控制放在对象(类)中某一个地方集中进行描述。这种方式要求设计者必须对对象的并发行为有整体的了解,还有可能带来继承异常,即在定义子类时,必须对父类的同步控制描述进行重定义,才能把新定义的方法考虑进来。

    分散控制方式是把对象的并发控制描述分布到对象的各方法上。其中一种方案是在对象各方法的实现中进行同步控制,对象无条件地接收消息,在消息的处理方法中,根据对象目前的状态决定是等待还是继续执行。这种方案的不足之处在于:被挂起的方法往往使得对象处于一种不稳定状态,使得对象此时不适合于处理其他消息;并且当在子类中改变父类某方法的同步控制时,需对整个方法重定义。另一种方案是在对象类中给每个方法加一个激励条件,当对象接收到消息时,将根据相应方法的激励条件来决定是否处理该消息,对不满足激励条件的消息让其等待。这种方案优于前一种方案,因为,当定义子类时可以对父类中各方法的激励条件和方法的实现分开进行继承,从而避免了不必要的重定义。

0
相关文章