面向对象的开发方法(Object Oriented,OO)
现在每个程序员都会说:OO思想,OO开发,呵呵,是真的理解了嘛?看看下面的文章就知道啦。。。
面向对象的开发方法(Object Oriented,OO)
从事软件开发的工程师们常常有这样 的体会:在软件开发过程中,使用者会不断地提出各种更改要求,即使在软件投入使用后,也常常需要对其做出修改,在用结构化开发的程序中,这种修改往往是很 困难的,而且还会因为计划或考虑不周,不但旧错误没有得到彻底改正,又引入了新的错误;另一方面,在过去的程序开发中,代码的重用率很低,使得程序员的效 率并不高,为提高软件系统的稳定性、可修改性和可重用性,人们在实践中逐渐创造出软件工程的一种新途径――面向对象方法学。
面向对象方法学的出发点和基本原则是尽可能模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界、解决问题的方法与过程。由于客观世界的问题都是由客观世界中的实体及实体相互间的关系构成的,因此我们把客观世界中的实体抽象为对象(Object)。持面向对象观点的程序员认为计算机程序的结构应该与所要解决的问题一致,而不是与某种分析或开发方法保持一致,他们的经验表明,对任何软件系统而言,其中最稳定的成分往往是其相应问题论域(problem domain)中的成分。(例如在过去几百年中复式计帐的原则未做任何实质性的改变,而其使用的工具早已从鹅毛笔变成了计算机。)
所以,“面向对象”是一种认识客观世界的世界观,是从结构组织角度模拟客观世界的一种方法。一般人们在认识和了解客观现实世界时,通常运用的一些构造法则:
-
区分对象及其属性,例如区分台式计算机和笔记本计算机;
-
区分整体对象及其组成部分,例如区分台式计算机组成(主机、显示器等);
-
不同对象类的形成以及区分,例如所有类型的计算机(大、中、小型计算机、服务器、工作站和普通微型计算机等)。
通俗地讲,对象指的是一个独立的、异步的、并发的实体,它能“知道一些事情” (即存储数据),“做一些工作”(即封装服务),并“与其它对象协同工作”(通过交换消息),从而完成系统的所有功能。
因为所要解决的问题具有特殊性,所以对象是不固定的。一个雇员可以作为一个对象,一家公司也可以作为一个对象,到底应该把什么抽象为对象,由所要解决的问题决定。
从以上的简单介绍中我们可以看出,面向对象所带来的好处是程序的稳定性与可修改性(由于把客观世界分解成一个一个的对象,并且把数据和操作都封装在对象的内部)、可复用性(通过面向对象技术,我们不仅可以复用代码,而且可以复用需求分析、设计、用户界面等等)。
1. 认为客观世界是由各种对象组成的,任何事物都是对象,复杂的对象可以由比较简单的对象以某种方式组合而成。按照这种观点,可以认为整个世界就是一个最复杂 的对象。因此,面向对象的软件系统是由对象组成的,软件中的任何元素都是对象,复杂的软件对象由比较简单的对象组合而成。
2.把所有对象都划分成各种对象类(简称为类(Class)),每个对象类都定义了一组数据和一组方法,数据用于表示对象的静态属性,是对象的状态信息。因此,每当建立该对象类的一个新实例时,就按照类中对数据的定义为这个新对象生成一组专用的数据,以便描述该对象独特的属性值。
例如,荧光屏上不同位置显示的半径不同的几个圆,虽然都是Circle类的对象,但是,各自都有自己专用的数据,以便记录各自的圆心位置、半径等等。
类中定义的方法,是允许施加于该类对象上的操作,是该类所有对象共享的,并不需要为每个对象都复制操作的代码。
3.按照子类(或称为派生类)与父类(或称为基类)的关系,把若干个对象类组成一个层次结构的系统(也称为类等级)。
4.对象彼此之间仅能通过传递消息互相联系。
二、OO方法的基本思想
对象:是事物运行方式、处理方法和属性值的一种抽象表述。它是严格信息包和有关信息包的操作描述;它是事物的本质,不会随周围环境改变而变化的相对固定的最小的集合。它可用一组属性和可以执行的一组操作来定义。
例:在计算机屏幕上画多边形,每个多边形是一个用有序顶点的集所定义的对象。
这些顶点的次序决定了它们的连接方式,顶点集定义了一个多边形对象的状态,包括它的形状和它在屏幕上的位置,在多边形上的操作包括:draw(屏幕显示)、 move(移动)、 contains(检查某点是否在多边形内)。
类的定义包括一组数据属性和在数据上的一组合法的操作。在一个类中,每个对象都是类的实例(instance)。同类的对象具有相同的方法集。
类还具有父类、子类之分。父类高层次的类,表达共性,子类低层次表达个性。子类通过继承机制获得父类的属性和操作。例如:电视机、电话、计算机等都是电子产品,它们具有电子产品的公共特性,当定义电视机类Video,电话类Telephone和计算机类Computer时候,为避免它们公共特性的重复编码,可将这些电子产品的公共特性部分定义为电子产品类,将Video,Telephone和Computer定义为它的子类,子类继承了父类的所有属性和操作,而且子类自己还可扩充定义自己的属性和操作:如电子产品类具有型号、价格、颜色等属性,computer则继承了这些属性,并扩充自己的属性:显示类型、内存大小等属性。
(1)古典法
候选的对象和类通常来自下列来源:
有形事物:汽车、气象数据、压力传感器。
角色:父亲、教师、医生、女兵。
事件:降落、中断、要求。
交互作用:借款、会议、交叉。
候选的对象还可能来自:
结构:“ 是一个”及“ …的部分”关系。
其它系统:与待研制系统有交往的其它系统。
承担的角色:用户与待研制系统交往时所承担的不同角色,如站长、站调、统计员等。
地点:待研制系统中重要的具体地点、办公处以及场所,如信号楼、技术科、调度室。
组织单位:用户所属组织,如生产部、经营部、总务处等。
(2)领域分析法
古典法是集中于问题的有形事物,而领域分析法则集中于问题领域中重要的对象、操作以及关系识别。其任务是在某一问题领域中识别出所有一切应用问题共有的客体和类,例如,销售、会计、债券交易、编译程序等都是问题领域。
领域分析法举例
例如,需要研制一个邮政销售(函售)系统,所考虑的函售应用问题如它们的关健对象一时想不出来,可对整个销售领域进行领域分析,即从现存的零售、批发系统中发现那些一时想不出来的对象,或得到启发而定出所需对象。
(3)结构化分析法
它是利用结构化分析的成果,如DFD(数据流程图)、实体关系图、数据字典等,找出和识别对象。
数据流程图中的数据存储、外部实体,有些非系统内部的数据流(它可来自外部的刺激或系统对外界的响应)等均可以作为候选对象。如存户来银行存款,即是外部对银行存款系统的的一个刺激,其数据内容是存户款;给存户的月终结算,是系统对外部的响应。
模块性:对象是一个独立存在的实体。从外部可以了解它的功能,其内部细节是“ 隐蔽”的, 不 受外界干扰。对象之间的相互依赖性很小。所以,模块性体现了抽象和信息的隐蔽。它使得一个复杂的软件系统可以通过定义一组相对独立的模块来实现,这些独立 模块彼此之间只需交换那些为了完成系统功能所必须交换的信息。当模块内部实现发生变化而导致代码修改时,只要对外接口操作的功能不变,就不会给软件系统带 来影响。
继承和类比性:对象之间属性关系的共同性,即子模块继承了父模块的属性;通过类比方法抽象出典型对象的过程为类比。
继承:是利用已有的定义作为基础来建立新的定义,而不必重复定义它们。
例如,汽车具有“ 型号”、“ 年代”和“ 引擎”等属性,其子类吉普车、轿车及卡车都继承了这些属性。
动态连接性:各个对象之间统一、方便、动态的消息传递机制。它是面向对象语言的共同特性,其含义是将一条发送给一个对象的消息与包含该消息的方法的对象联接起来,它使得增加新的数据类型不需要改变现有的代码。
3.以对象为主体的OO方法
(1)客观事物都是由对象(object)组成的,对象是在原事物基础上抽象的结果。任何复杂的事物都可以通过对象的组合构成。
(2)对象由属性(attribute)和方法组成。属性反映了对象的信息特征,如:特点、值、状态等等;方法(method)则是用来定义改变属性状态的各种操作。
例如:电视机对象的属性有颜色、音量、亮度、频道等,其上的操作有调节颜色、调节音量、调节亮度、调节频道等。
如:图书馆系统中其业务过程和业务实体中,最基本的对象类只有读者和复本。最基本的业务操作只有借阅和查询。
(3)对象之间的联系主要是通过传递消息(message)来实现的,而传递的方式是通过消息模式(message pattern)和方法所定义的操作过程来完成的。
例如当用户请求document的对象打印它自己时,该文档可发送一消息给对象printer以在打印队列中请求一位置,而printer则可发送一消息 返回至该文档以要求对信息加以格式化。消息还可包含解释一请求的信息。如请求一对象打印其自身的消息可包含打印机名。
(4)对象可按照其属性进行归类(class),类有一定的结构,类上有超类(父类),类下有子类。这种对象或类之间的层次结构是靠继承关系维系着的。一般父类具有通用性,子类具有特殊性。例如:
图4-4-1 类、子类、超类关系
segment是一个对象,paragraph和table共享某些性质,则可用更抽象的类text表示;paragraph也是一个类,它虽是segment的父类却是text的子类,text是类document的子类,text是table的超类(父类)。
又如汽车是轿车、吉普车及卡车的父类,轿车、吉普车及卡车是汽车的子类。父类和子类是相对的。父类之上可有另一父类,而成为其子类。
(5)对象是一个被严格模块化的实体,称为封装(encapsulation)。这种封装了的对象满足软件工程的一切要求,而且可以直接被面向对象的程序设计语言所接受。
例如,电视机箱将电视内部的显象管、印刷板、元件和线路都封装起来了。人们只能通过电视机面板上按钮改变其属性(颜色、音量、亮度、频道、制式等)。
有关对象的概念还有下列相关的一些内容:
实例就是由某个特定的类所描述的一个具体的对象。类是对具有相同属性和行为的一组相似的对象的抽象,类在现实世界中并不能真正存在。在地球上并没有抽象的“中国人”,只有一个个具体的中国人,例如,张三、李四、王五,同样,谁也没见过抽象的“圆”。
实际上类是建立对象时使用的“样板”,按照这个样板所建立的一个个具体的对象,就是类的实际例子,通常称为实例。
对 象之间进行通信的一种构造叫做消息,当一个消息发送给某个对象时,包含要求接收对象去执行某些活动的信息。接收到消息的对象经过解释,然后予以响应。这种 通信机制叫做消息传递。发送消息的对象不需要知道接收消息的对象如何对请求予以响应。通常,一个消息由下述三部分组成:
(a)接收消息的对象;
(b)消息选择符(也称为消息名);
(c)零个或多个变元。
方法,就是对象所能执行的操作,也就是类中所定义的服务。方法描述了对象执行操作的算法,响应消息的方法。在C++语言中把方法称为成员函数。
例如,在录音机的例子中,为了能让使用者按下“放音键”就开始播放磁带,必须在录音机类中给出“按下放音键”的定义,也就是给出这个动作的实现方法。
属性,就是类中所定义的数据,它是对客观世界实体所具有的性质的抽象。类的每个实例都有自己特有的属性值。
例如,在录音机类中定义的代表录音机的型号、外观、电压等数据就是属性。
广义地说,继承是指能够直接获得已有的性质和特性,而不必重复定义它们。在面向对象的软件技术中,继承是子类自动地共享基类(或父类)中定义的数据和方法的机制。一个类直接继承其父类的全部描述(数据和操作)。
继承具有传递性,继承性使得相似的对象可以共享程序代码和数据结构,从而大大减少了程序中的冗余信息。使得对软件的修改变得比过去容易得多了。
继承性使得用户在开发新的应用系统时不必完全从零开始,可以继承原有的相似系统的功能或者从类库中选取需要的类,再派生出新的类以实现所需要的功能,所以,继承的机制主要是支持程序的重用和保持接口的一致性。
在 面向对象的软件技术中,多态性是指子类对象可以像父类对象那样使用,同样的消息既可以发送给父类对象也可以发送给子类对象。也就是说,在类等级的不同层次 中可以共享(公用)一个行为(方法)的名字,然而不同层次中的每个类却各自按自己的需要来实现这个行为。当对象接收到发送给它的消息时,根据该对象所属于 的类动态选用在该类中定义的实现算法。
有两种重载:函数重载是指在同一作用域内的若干个参数特征不同的函数可以使用相同的函数名字;运算符重载是指同一个运算符可以施加于不同类型的操作数上面。当然,当参数特征不同或被操作数的类型不同时,实现函数的算法或运算符的语义是不相同的。
重载进一步提高了面向对象系统的灵活性和可读性。
OO方法开发过程分为4个阶段:
1.系统调查和需求分析:对系统面临的问题和用户的开发需求进行调查研究。
2.分析问题的性质和求解问题:在复杂的问题域中抽象识别出对象及其行为、结构、属性和方法。这一个阶段一般称为面向对象分析,即OOA。
3.整理问题:对分析的结果进一步抽象、归类整理,最终以范式的形式确定下来,即OOD。
4.程序实现:使用面向对象的程序设计语言将其范式直接映射为应用程序软件,即OOP(它是一个直接映射过程)。
本节着重讨论面向对象分析(Object-Oriented Analysis, OOA)。
面向对象分析与其它分析方法一样,是提取系统需求的过程。
面向对象分析的关键,是识别出问题域内的对象,并分析他们相互间的关系,最终建立起问题域的正确模型。
通 常,面向对象分析过程从分析陈述用户需求的文件开始。需求陈述的内容包括:问题范围,功能需求,性能需求,应用环境及假设条件等。总之,需求陈述应该阐明 “做什么”而不是“怎样做”。它应该描述用户的需求而不是提出解决问题的方法。在利用面向对象开发方法时,书写需求陈述要尽力做到语法正确,而且应该慎重 选用名词、动词、形容词和同义词。
接下来,系统分析员应该深入理解用户需求,抽象出目标系统的本质属性,并用模型准确地表示出来。
面向对象分析大体上按照下列顺序进行:建立功能模型、建立对象模型、建立动态模型、定义服务。
1.建立功能模型
功能模型从功能角度描述对象属性值的变化和相关的函数操作,表明了系统中数据之间的依赖关系以及有关的数据处理功能,它由一组数据流图组成。其中的处理功能可以用IPO图、伪码等多种方式进一步描述。
建立功能模型首先要画出顶层数据流图,然后对顶层图进行分解,详细描述系统加工、数据变换等,最后描述图中各个处理的功能。
2.建立对象模型
复杂问题(大型系统)的对象模型由下述五个层次组成:主题层(也称为范畴层)、类-&-对象层、结构层、属性层和服务层,如图4-4-2所示。
图4-4-2 对象模型的层次
这五个层次很像叠在一起的五张透明塑料片,它们一层比一层显现出对象模型的更多细节。在概念上,这五个层次是整个模型的五张水平切片。
建立对象模型典型的工作步骤是:首先确立对象类和关联,对于大型复杂的问题还要进一步划分出若干主题;然后给类和关联增添属性,以进一步描述它们;接下来利用适当的继承关系进一步合并和组织类。
(1)确定类-&-对象
类-&-对象是在问题域中客观存在的,系统分析员的主要任务就是通过分析找出这些类-&-对象。首先,找出所有候选的类-&-对象;然后,从候选的类-&-对象中筛选掉不正确的或不必要的项。
步骤1:找出候选的类-&-对象
对象是对问题域中有意义的事物的抽象,它们既可能是物理实体,也可能是抽象概念,在分析所面临的问题时,可以参照几类常见事物,找出在当前问题域中的候选类-&-对象。
另一种更简单的分析方法,是所谓的非正式分析。这种分析方法以用自然语言书写的需求陈述为依据,把陈述中的名高速作为类-&- 对象的候选者,用形容词作为确定属性的线索,把动高速作为服务(操作)候选者。当然,用这种简单方法确定的候选者是非常不准确的,其中往往包含大量不正确 的或不必要的事物,还必须经过更进一步的严格筛选。通常,非正式分析是更详细、更精确的正式的面向对象分析的一个很好的开端。
步骤2:筛选出正确的类-&-对象
非正式分析仅仅帮助我们找到一些候选的类-&-对象,接下来应该严格考察候选对象,从中去掉不正确的或不必要的,仅保留确实应该记录其信息或需要其提供服务的那些对象。筛选时主要依据下列标准,删除不正确或不必要的类-&-对象:
<1>冗余(如果两个类表达了同样的信息)
<2>无关(仅需要把与本问题密切相关的类-&-对象放进目标系统中)
<3>笼统(需求陈述中笼统的、泛指的名词)
<4>属性(在需求陈述中有些名词实际上描述的是其它对象的属性)
<5>操作(正确地决定把某些词作为类还是作为类中定义的操作)
<6>实现(去掉仅和实现有关的候选的类-&-对象)
(2)确定关联
两个或多个对象之间的相互依赖、相互作用的关系就是关联。分析确定关联,能促使分析员考虑问题域的边缘情况,有助于发现那些尚未被发现的类-&-对象。
步骤1.初步确定关联
在 需求陈述中使用的描述性动词或动词词组,通常表示关联关系。因此,在初步确定关联时,大多数关联可以通过直接提取需求陈述中的动词词组而得出。通过分析需 求陈述,还能发现一些在陈述中隐含的关联。最后,分析员还应该与用户及领域专家讨论问题域实体间的相互依赖、相互作用关系,根据领域知识再进一步补充一些 关联。
步骤2.自顶向下
把现有类细化成更具体的子类,这模拟了人类的演绎思维过程。从应用域中常常能明显看出应该做的自顶向下的具体化工作。例如,带有形容词修饰的名词词组往往暗示了一些具体类。但是,在分析阶段应该避免过度细化。
(3)定义结构
结构指的是多种对象的组织方式,用来反映问题空间中的复杂事物和复杂关系。这里的结构包括两种:分类结构与组装结构。分类结构针对的是事物的类别之间的组织关系,组织结构则对应着事物的整体与部件之间的组合关系。
使 用分类结构,可以按事物的类别对问题空间进行层次化的划分,体现现实世界中事物的一般性与特殊性。例如在交通工具、汽车、飞机、轮船这几件事物中,具有一 般性的是交通工具,其它则是相对特殊化的。因此可以将汽车、飞机、轮船这几种事物的共有特征概括在交通工具之中,也就是把对应于这些共有特征的属性和服务 放在“交通工具”这种对象之中,而其它需要表示的属性和服务则按其特殊性放在“汽车”、“飞机”、“轮船”这几种对象之中,在结构上,则按这种一般与特殊 的关系,将这几种对象划分在两个层次中,如图4-4-3所示:
4-4-3 分类结构示例
组织结构表示事物的整体与部件之间的关系。例如把汽车看成一个整体,那么发动机、变速箱、刹车装置等都是汽车的部件,相对于汽车这个整体就分别是一个局部。
(4)识别主题
对 一个实际的目标系统,特别是大的系统而言,尽管通过对象和结构的认定对问题空间中的事物进行了抽象和概括,但对象和结构的数目仍然是可观的,因此如果不对 数目众多的对象和结构进行进一步的抽象,势必造成对分析结果理解上的混乱,也难以搞清对象、结构之间的关联关系,因此引入主题的概念。
主题是一种关于模型的抽象机制,它给出了一个分析模型的概貌。
主 题直观地来看就是一个名词或名词短语,与对象的名字类似,只是抽象的程度不同。识别主题的一般方法是:为每一个结构追加一个主题;为每一种对象追加一个主 题;如果当前的主题的数目超过了7个,就对已有的主题进行归并,归并的原则是,当两个主题对应的属性和服务有着较密切的关联时,就将它们归并成一个主题。
(5)认定属性
属性是数据元素,用来描述对象或分类结构的实例。
认定一个属性有三个基本原则:首先,要确认它对响应对象或分类结构的每一个实例都是适用的;其次,对满足第一个条件的属性还要考察其在现实世界中与这种事物的关系是不是足够密切;第三,认定的属性应该是一种相对的原子概念,即不依赖于其它并列属性就可以被理解。
3.建立动态模型
当问题涉及交互作用和时序时(例如用户界面及过程控制等),建立动态模型则是很重要的。
建立动态模型的第一步,是编写典型交互行为的脚本。脚本是指系统在某一执行期间内出现的一系列事件。编写脚本的目的,是保证不遗漏重要的交互步骤,它有助于确保整个交互过程的正确性和清晰性。
第二步从脚本中提取出事件,确定触发每个事件的动作对象以及接受事件的目标对象。
第三步,排列事件发生的次序,确定每个对象可能有的状态以及状态间的转换关系。
最后,比较各个对象的状态,检查它们之间的一致性,确保事件之间的匹配。
4.定义服务
通常在完整地定义每个类中的服务之前,需要先建立起动态模型和功能模型,通过对这两种模型的研究,能够更正确更合理地确定每个类应该提供那些服务。
正如前面已经指出的那样,“对象”是由描述其属性的数据,及可以对这些数据施加的操作(即服务)封装在一起构成的独立单元。因此,为建立完整的动态模型, 既要确定类的属性,又要定义类的服务。在确定类中应有的服务时,既要考虑类实体的常规行为,又要考虑在本系统中特殊需要的服务。
首先考虑常规行为:在分析阶段可以认为类中定义的每个属性都是可以访问的,即假设在每个类中都定义了读、写该类每个属性的操作。
其次,从动态模型和功能模型中总结出特殊服务。
最后应该尽量利用继承机制以减少所需定义的服务数目。
五、OOD方法(面向对象的设计)
如前所述,分析是提取和整理用户需求,并建立问题域精确模型的过程。设计则是把分析阶段得到的需求转变成符合成本和质量要求的、抽象的系统实现方案的过程。从面向对象分析到面向对象设计(通常缩写为OOD),是一个逐渐扩充模型的过程。或者说,面向对象设计就是用面向对象观点建立求解域模型的过程。
尽 管分析和设计的定义有明显区别,但是在实际的软件开发过程中二者的界限是模糊的。许多分析结果可以直接映射成设计结果,而在设计过程中又往往会加深和补充 对系统需求的理解,从而进一步完善分析结果。因此,分析和设计活动是一个多次反复迭代的过程。面向对象方法学在概念和表示方法上的一致性,保证了在各项开 发活动之间的平滑(无缝)过渡,领域专家和开发人员能够比较容易地跟踪整个系统开发过程,这是面向对象方法与传统方法比较起来所具有的一大优势。
在以前的软件设计中人们总结出几条基本原理,这些原理在进行面向对象设计时仍然成立,但是增加了一些与面向对象方法密切相关的新特点,从而具体化为下列的面向对象设计准则:
(1) 模块化
面向对象软件开发模式,很自然地支持了把系统分解成模块的设计原理:对象就是模块。它是把数据结构和操作这些数据的方法紧密地结合在一起所构成的模块。
(2) 抽象
抽象表示对规格说明的抽象(abstraction by specification)和参数化抽象(abstraction by parametrization)。
(3) 信息隐藏
在面向对象方法中,信息隐藏通过对象的封装性实现:类结构分离了接口与实现,从而支持了信息隐藏。对于类的用户来说,属性的表示方法和操作的实现算法都应该是隐藏的。
(4) 弱耦合
在面向对象方法中,对象是最基本的模块,因此,耦合主要指不同对象之间朴素关联的紧密程度。弱耦合是优秀设计的一个重要标准,因为这有助于使得系统中某一部分的变化对其它部分的影响降到最低程度。
当然,对象不可能是完全孤立的,当两个对象必须朴素联系、朴素依赖时,应该通过类的协议(即公共接口)实现耦合,而不应该依赖于类的具体实现细节。
(5) 强内聚
设计中使用的一个构件内的各个元素,对完成一个定义明确的目的所做出的贡献程度。在设计时应该力求做到高内聚。在面向对象设计中存在下述三种内聚:
<1>服务内聚
一个服务应该完成一个且仅完成一个功能。
<2>类内聚
一个类应该只有一个用途。
<3>一般-特殊内聚
设计出的一般-特殊结构,应该符合多数人的概念。
(6) 可重用
软件重用是 提高软件开发生产率和目标系统质量的重要途径。重用也叫再用或复用,是指同一事物不作修改或稍加改动就多次重复使用。重用是从设计阶段开始的。重用有两方 面的含义:一是尽量使用已有的类(包括开发环境提供的类库,及以往开发类似系统时创建的类),二是如果确实需要创建新类,则在设计这些新类的协议时,应该 考虑将来的可重复使用性。
软件成分的重用可以进一步划分成以下三个级别:
<1>代码重用
<2>设计结果重用
设计结果重用指的是,重用某个软件系统的设计模型(即求解域模型)。这个级别的重用有助于把一个应用系统移植到完全不同的软/硬平台上。
<3>分析结果重用
这是一种更高级别的重用,即重用某个系统的分析模型。这种重用特别适用于用户需求未改变,但系统体系结构发生根本变化的场合。
通 过分析软件重用的效果发现,重用率越高,生产率并不一定就越高。仅当开发人员使用已有软构件构造系统时,其工作效率比重新从底层编写程序的效率高时,重用 率的提高才会导致生产率提高。可见,通过软件重用来提高软件生产率,并不是一件轻而易举的事情。软构件的实用程序和程度,以及软件开发人员的素质、开发环 境等因素,都直接影响软件重用的效果。事实上,自20世纪60年代以来,人们就开始研究软件重用技术,主要目的是大幅度提高软件生产率,降低软件成本。但是,多年来始终没能有效地实现软件重用,直到面向对象技术崛起之后,才为软件重用带来了新的希望。
2.面向对象设计的内容
采用面向对象方法设计软件系统时,面向对象设计模型(即求解域的对象模型)与面向对象分析模型(即求问题域的对象模型)一样,也由主题、类-&- 对象、结构、属性、服务等五个层次组成。这五个层次表示的细节一层比一层多,我们可以把这五个层次想象为整个模型的水平切片。此外,大多数系统的面向对象 设计模型,在逻辑上都由四大部分组成。这四大部分对应于组成目标系统的四个子系统,它们分别是问题域子系统、人-机交互子系统、任务管理子系统和数据管理 子系统。
通过面向对象分析所得出的问题域精确模型,为设计问题域子系统奠定了良好的基础,建立了完整的框架。只要可能,就应该保持面向对象分析所建立的问题域结构。通常,面向对象设计仅需从实现角度对问题域模型作一些补充或修改,主要是增添、合并或分解类-&-对象、属性及服务,调整继承关系等等。当问题域子系统过分复杂庞大时,应该把它进一步分解成若干个更小的子系统。
下面介绍在面向对象设计过程中,可能对面向对象分析所得出的问题域模型的补充或修改:
<1>调整需求
有两种情况出现需要调整需求:用户需求或外部环境发生了变化;分析员对问题的理解存在问题。无论哪种情况出现,通常都只需要简单地修改分析的结果,然后把这些修改的结果反映到问题域子系统中。
<2>重用已有的类
代码重用从设计阶段开始,在研究面向对象分析结果时就应该寻找使用已有类的方法。若因为没有合适的类可以重用而确实需要创建新的类,则在设计这些新类的协议时,考虑到将来的可重用性。
<3>把问题域类组合在一起
在面向对象设计过程中,设计者往往通过引入一个根类而把问题域组合在一起,但这是在没有更先进的组合机制时才采用的一种组合方法。
<4>增添一般化类以建立协议
在设计过程中常常发现,一些具体类需要有一个公共的协议,也就是说,它们都需要定义一组类似的服务(很可能还需要相应的属性)。在这种情况下可以引入一个附加类(例如,根类)。
<5>调整继承层次
如果面向对象分析模型中包含了多重继承关系,然而所使用的程序设计语言却并不提供多重继承机制,则必须修改面向对象分析的结果。即使使用支持多重继承的语言,有时也会出于实现考虑而对面向对象分析结果作一些调整。
在面向对象分析过程中,已经对用户界面需求作了初步分析,在面向对象设计过程中,则应该对系统的人-机子系统进行详细设计,以确定人-机交互的细节,其中包括指定窗口和报表的形式、设计命令层次等项内容。人-机交互部分的设计结果,将对用户情绪和工作效率产生重要影响。
<1> 设计人-机交互界面的准则
一致性
减少步骤
及时提供反馈信息
提供撤消命令
无须记忆
易学
富有吸引力
<2>设计人-机交互子系统的策略
-
分类用户
为设计好人-机交互子系统,设计者应该认真研究使用它的用户。设计者首先应该把将来可能与系统交互的分类。通常从下列几个不同角度进行分类:
按技能水平分类(新手/初级/中级/高级)。
按职务分类(总经理/经理/职员)。
按所属集团分类(职员/顾客)。
-
描述用户
应该仔细了解未来使用系统的每类用户的情况,把获得的下列各项信息记录下来:
用户类型。
使用系统欲达到的目的。
特征(年龄、性别、受教育程度、限制因素等)。
关键的成功因素(需求、爱好、习惯等)。
技能水平。
完成本职工作的脚本。
-
设计命令层次
设计命令层次的工作通常包含以下几项内容:
研究现有的人-机交互含义和准则
现在,Windows已经成了微机上图形用户界面事实上的工业标准。
确切初始的命令层次
所谓命令层次,实质上是用过程抽象机制组织起来的、可供选用的服务的表示形式。
精化命令层次
精化命令层次应考虑以下因素:次序、整体---部分关系、操作步骤。
-
设计人-机交互类
人-机交互类与所使用的操作系统及编程语言密切相关。
虽 然从概念上说,不同对象可以并发地工作。但是,在实际系统中,许多对象之间往往存在相互依赖关系。此外,在实际使用的硬件中,可能仅由一个处理器支持多个 对象。因此,设计工作的一项重点就是,确定哪些是必须同时操作的对象,哪些是相互排斥的对象。然后进一步设计任务管理子系统。
<1> 分析并发性
彼 此间不存在交互,或者它们同时接受事件,则这两个对象在本质上是并发的。通过检查各个对象的状态图及它们之间交换的事件,能够把若干个非并发的对象归并到 一条控制线中。所谓控制线,是一条遍及状态图集合的路径,在这条路径上每次只有一个对象是活动的。在计算机系统中用任务(task)实现控制线,一般认为任务是进程(process)的别名。通常把多个任务的并发执行称为多任务。
<2> 设计任务管理子系统
常见的任务有事件驱动型任务、时钟驱动型任务、优先任务、关键任务和协调任务等。设计任务管理子系统,包括确定各类任务并把任务分配给适当的硬件或软件去执行。
-
确定事件驱动型任务
某些任务是由事件驱动的,这类任务可能主要完成通信工作。例如,设备、屏幕窗口、其它任务、子系统、另一个处理器或其它系统通信。事件通常是表明某些数据到达的信号。
-
确定时钟驱动任务
某些任务每隔一定时间间隔就被触发以执行某些处理,例如,某些设备需要周期性地获得数据;某些人-机接口、子系统、任务、处理器或其它系统也可能需要周期性地通信。在这些场合往往需要使用时钟驱动型任务。
-
确定优先任务
优先任务可以满足高优先级或低优先级的处理需求。
高优先级:某些服务具有很高的优先级,为了在严格限定的时间内完成这种服务,可能需要把这类服务分离成独立的任务。
低优先级:与高优先级相反,有些服务是低优先级的,属于低优先级处理(通常指那些背景处理)。设计时可能用额外的任务把这样的处理分离出来。
-
确定关键任务
关键任务是关系到系统成功或失败的那些关键处理,这类处理通常都有严格的可靠性要求。
-
确定协调任务
当系统中存在三个以上任务时,就应该增加一个任务,用它作为协调任务。
-
确定资源需求
使用多处理器或固件,主要是为了满足高性能的需求。设计者必须通过计算系统载荷来估算所需要的CPU(或其它固件)的处理能力。
数据管理子系统是系统存储或检索对象的基本设施,它建立在某种数据存储管理系统之上,并且隔离了数据存储管理模式。
<1> 选择数据存储管理模式
文 件管理系统、关系数据库管理系统、面向对象数据管理系统三种数据存储管理模式有不同的特点,适用范围也不同,其中文件系统用来长期保存数据,具有成本低和 简单等特点,但文件操作级别低,为提供适当的抽象级别还必须编写额外的代码;关系数据库管理系统提供了各种最基本的数据管理功能,采用标准化的语言,但其 缺点是运行开销大,数据结构比较简单;面向对象数据管理系统增加了抽象数据类型和继承机制,提供了创建及管理类和对象的通用服务。
<2> 设计数据管理子系统
设计数据管理子系统,既需要设计数据格式又需要设计相应的服务。设计数据格式包括用范式规范每个类的属性表以及由此定义所需的文件或数据库;设计相应的服务是指设计被存储的对象如何存储自己。
面向对象实现主要包括两项工作:把面向对象设计结果翻译成用某种程序语言书写的面向对象程序;测试并调试面向对象的程序。
面向对象程序的质量基本上由面向对象设计的质量决定,但是,所采用的程序语言的特点和程序设计风格也将对程序的生成、可重用性及可维护性产生深远影响。
1.程序设计
(1)面向对象的语言与非面向对象的语言
到底应该选用面向对象语言还是非面向对象语言,关键不在于语言功能强弱。选择编程语言的关键因素,是语言的一致的表达能力、可重用性及可维护性。从面向对象观点看来,能够更完整、更准确地表达问题和语义的面向对象语言的语法是非常重要的,因为这会带来下述几个重要优点:
面向对象语言的形成借鉴了历史上许多程序语言的特点,从中吸取了丰富的营养。当今的面向对象语言,从50年代诞生的LISP语言中引进了动态联编的概念和交到式开发环境的思想,从60年代推出的SIMULA语言中引进了类的概念和继承机制,此外,还受到70年代末期开发的Modula-2语言和Ada语言中数据抽象机制的影响。
100年代以来,面向对象语言像雨后春笋一样大量涌现,形成了两大类面向对象语言。一类是纯面向对象语言,如Smalltalk和Eiffel等语言。另一类是混合型面向对象语言,也就是在过程语言的基础上增加面向对象机制,如C++等语言。
一般说来,纯面向对象语言着重支持面向对象方法研究和快速原型的实现,而混合型面向对象语言的目标则是提高运行速度和使传统程序员容易接受面向对象思想。成熟的面向语言通常都提供丰富的类库和强有力的开发环境。
下面介绍在选择面向对象语言时应该着重考察的一些技术特点。
<1>支持类与对象概念的机制
所有面向对象语言都允许用户动态创建对象,并且可以用指针引用动态创建的对象。允许动态创建对象,就意味着系统必须处理内存管理问题,如果不及时释放不再需要的对象所占用的内存,动态存储分配就有可能耗尽内存。
<2>实现整体--部分结构的机制
一般说来,有两种实现方法,分别使用指针和独立的关联对象实现整体一部分结构。大多数现有的面向对象语言并不显示支持独立的关联对象,在这种情况下,使用指针是最容易的实现方法,通过增加内部指针可以方便地实现关联。
<3>实现一般--特殊结构的机制
既 包括实现继承的机制也包括解决名字冲突的机制。所谓解决名字冲突,指的是处理在多个基类中可能出现的重名问题,这个问题仅在支持多重继承的语言中才会遇 到。某些语言拒绝接受有名字冲突的程序,另一些语言提供了解决冲突的协议。不论使用何种语言,程序员都应该尽力避免出现名字冲突。
<4>实现属性和服务的机制
对于实现属性的机制应该着重考虑以下几个方面:支持实例连接的机制;属性的可见性控制;对属性值的约束。对于服务来说,主要应该考虑下列因素:支持消息连接(即表达对象交互关系)的机制;控制服务可见性的机制;动态联编。
<5>类型检查
程序设计语言可以按照编译时进行类型检查的严格程度来分类。如果语言仅要求每个变量或属性隶属于一个对象,则是弱类型的;如果语法规定每个变量或属性必须准确地隶属于某个特定的类,则这样的语言是强类型的。
<6>效率
许多人认为面向对象语言的主要缺点是效率低。事实上,如有完整类库的面向对象语言,有时能比使用非面向对象语言得到运行更快的代码。这是因为类库中提供了更高效的算法和更好的数据结构。
<7>持久保存对象
<8>参数化类
所 谓参数化类,就是使用一个或多个类型去参数化一个类型的机制,有了这种机制,程序员就可以先定义一个参数化的类模板(即在类定义中包含以参数形式出现的一 个或多个类型),然后把数据类型作为参数传递进来,从而把这个类模板用在不同的应用程序中,或用在同一应用程序的不同部分。Eiffel语言中就有参数化类,C++语言也提供了类模板。
<9>开发环境
软件工具和软件工程环境对软件生产率有很大影响。由于面向对象程序中继承关系和动态联编等引入的特殊复杂性,面向对象语言所提供的软件工具或开发环境就显得尤其重要了。至少应该包括下列一些最基本的软件工具:编辑程序,编译程序或解释程序,浏览工具,调试器(debugger)等。
(2)程序设计风格
良好的程序设计风格对保证程序质量的重要性。良好的程序设计风格对面向对象实现来说尤其重要,不仅能明显减少维护或扩充的开销,而且有助于在新项目中重用已有的程序代码。
良好的面向对象程序设计风格,既包括传统的程序设计风格和准则,也包括为适应面向对象方法所特有的概念(例如,继承性)而必须遵循的一些新准则。
<1>提高可重用性
面向对象方法的一个主要目标,就是提高软件的可重用性。正如本书11.3节所述,软件重用有多个层次,在编码阶段主要涉及代码重用问题。一般说来,代码重用有两种:一种是本项目内的代码重用,另一种是新项目重用旧项目的代码。内部重用主要是找出设计中相同或相似的部分,然后利用继承机制共享它们。
-
提高方法的内聚
-
减小方法的规模
-
保持方法的一致性
保持方法的一致性,有助于实现代码重用。一般说来,功能相似的方法应该有一致的名字、参数特征(包括参数个数、类型和次序)、返回值类型、使用条件及出错条件等。
-
把策略与实现分开
-
全面覆盖
如果输入条件的各种组合都可能出现,则应该针对所有组合写出方法,而不能仅仅针对当前用到的组合情况写方法。
此外,一个方法不应该只能处理正常值,对空值、极限值及界外值等异常情况也应该能够作出有意义的响应。
-
尽量不使用全局信息
应该尽量降低方法与外界的耦合程度,不使用全局信息是降低耦合度的一项主要措施。
-
利用继承机制
在面向对象程序中,继承机制是实现共享和提高重用程度的主要途径。
有时提高相似类代码可重用性的一个有效途径,是从不同类的相似方法中分解出不同的“因子”(即不同的代码),把余下的代码作为分用方法中的公共代码,把分解出的因子作为名字相同算法不同的方法,放在不同类中定义,并被这个公用方法调用。
程序员往往希望重用其它方法编写的、解决同一类应用问题的程序代码。重用这类代码的一个比较安全的途径,是把被重用的代码封装在类中。
<2> 提高健壮性
为提高健壮性应遵守以下几条准则:预防用户的误操作,不要预先限制条件,先测试后优化。
一般说来,对面向对象软件的测试可分为下列四个层次进行:
(1)算法层
测试类中定义的每个方法,基本上相当于传统软件测试中的单元测试。
(2)类层
测试封装在同一个类中的所有方法与属性之间的相互作用。在面向对象软件中类是基本模块,因此可以认为这是面向对象测试中所特有的模块(单元)测试。
(3)主题层
测试一组协同工作的类-&-对象之间的相互作用。大体上相当于传统软件测试中的子系统测试,但是也有面向对象软件的特点(例如,对象之间通过发送消息相互作用)。
(4)系统层
把各个子系统组装完整的面向对象软件系统,在组装过程中同时进行测试。
设 计测试方案的传统技术,例如,逻辑覆盖、等价划分、边界值分析和错误推测等方法,仍然可以作为测试类中每个方法的主要技术。面向对象测试的主要目标,也是 用尽可能低的测试成本和尽可能少的测试方案,发现尽可能多的错误。但是,面向对象程序中特有的封装、继承和多态等机制,也给面向对象测试带来一些新特点, 增加了测试和调试的难度。
七、面向对象的语言(产品)
面向对象的语言应该具备的特征:
1.用对象而非过程(功能或算法)作为程序设计的基本逻辑构件;
2.每个对象属于应该类(型),并为该类的一个实例;
3.一个类可继承其它类的性质。
面向对象的语言有:
1.SmallTalk-76,80,(80年代下半叶)
2.Actor(80年代下半叶)
3.C++,Objective-C (20世纪80年代下半叶)
4.Object Pascal, Object-Oriented Turbo Pascal,Apple ObjectPascal (80年代初开始)
5.Eiffel (80年代上半叶)
6.Ada9X
但Microsoft Visual C++, Boland C++等都属于混合型面向对象的语言,因为它们是在原来的过程语言的基础上发展起来的,都保留了原来的数据类型,如整数、浮点数、字符以及记录等。
几个有代表性的商品软件
Microsoft Visual Basic先从软件的可视化、速成化和组件化开始的,这3化已经开始或正在形成信息与软件工艺的主流之一。
Bland Delphi是组件软件和复合文书工艺的软件。它包含面向对象Pascal的编辑程序、查错程序、可视研制环境和工具、强大的数据库存取(BDE-Database Engine)工具;它用Object Pascal做情节描述语言。
Optima++ Developer 是 Sybase/Powersoft出版的可视化、速成化的研制工具。它是采用C++的一种纯可视编辑工具,用拖扔编程技术,从一组标准的和可增的控件制模 板中拖出组件,将其扔进应用图表中去,并编辑其性质。它可在Windows 9X和NT下运行,它不仅是一个GUI(图形用户接口)建造程序,而且还是一个C/S(客户/服务器)数据库构造工具。
IBM的VisualAge(SmallTalk版),用一套图标来代表应用组件(对象),并提供许多标准函数(例程)、部件,供GUI配置关系数据库存取、通信、等之用。
用户编程时,只需用鼠标把要用的部件(图标)拖扔到屏幕中的工作面内,按要求设置这些图标的缺省项和参数值,再把这些图标用线段连接起来,表示它 们之间的关系和交互操作,并最后加以测试。在组装过程中,要添加复杂的计算/控件流,可用VisualAge的描述语言(Scripting Language-一种4GL)来编写。如果这还不行,VisualAge则提供SmallTalk编辑环境,以添加所需的语句。
Digitalk(现叫ParcPlace-Digitalk)的Visual Smalltalk提 供组件组装的可视研制环境和工具,用拖扔手段,可视地把组件组装成一个软件(程序),它还能自建新的组件。它最适宜研制软件雏形的OO程序设计语言。应用 完成之后,使用Digitalk Smalltalk编译程序编译,其计算效率据称可增加25%,GUI效率增加了100%。
Prograph CPX(跨平台)将程序面向对象结构的可视化方面做得较突出:
-它用图标代表一个软件的组成部分,对象、类、组件全部可视化;
-全套图标都用多面体图标,如类具有“ 方法”面和“ 属性”面;
-能对图标加以注释,对象和类关系可用线段表示;
-通过工具可方便地将方法加入Tools菜单;
-既有解释程序、又有编译程序,可解除解释程序速度慢的问题。
1.特点
(1)利用特定软件直接从对象客体的描述到软件结构的转换。
(2)解决了传统结构化方法中客观世界描述工具与软件结构的不一致性。
(3)减少了从系统分析、设计到软件模块结构之间的多次转换映射的繁杂过程。
优点:
(1)是一种全新的系统分析设计方法(对象、类、结构属性、方法)。
(2)适用于各类信息系统的开发。
(3)实现了对客观世界描述到软件结构的直接转换 ,大大减少后续软件开发量。
(4)开发工作的重用性、继承性高,降低重复工作量。
(5)缩短了开发周期。
缺点:
(1)需要一定的软件支持环境。
(2)不太适宜大型的MIS开发,若缺乏整体系统设计划分,易造成系统结构不合理、各部分关系失调等问题。
(3)只能在现有业务基础上进行分类整理,不能从科学管理角度进行理顺和优化。
(4)初学者不易接受、难学。
面向对象方法学把分析、设计和实现很自然地联系在一起了。虽然面向对象设计原则上不依赖于特定的实现环境,但是实现结果和实现成本却在很大程度上取决于实现环境。因此,直接支持面向对象设计范式的面向对象程序语言、开发环境及类库,对于面向对象实现来说是非常重要的。
为了把面向对象设计结果顺利地转变成面向对象程序,首先应该选择一种适当的程序设计语言。面向对象的程序设计语言适合用来实现面向对象设计结果。事实上,具有方便的开发环境和丰富的类库的面向对象程序设计语言,是实现面向对象设计的最佳选择。
良好的程序设计风格对于面向对象实现来说格外重要。它既包括传统的程序设计风格准则,也包括与面向对象方法的特点相适应的一些新准则。
面向对象方法学使用独特的概念和完成软件开发工作,因此,在测试面向对象程序的时候,除了继承传统的测试技术之外,还必须研究与面向对象程序特点相适应的新的测试技术。在这方面需要做的研究工作还很多,目前已逐渐成为国内外软件工程界研究的一个新的热门课题。
完毕!!!!!!!!!!!!
大家在使用的过程中有什么好的想法或见解,都可以说出来与大家分享一下。有了自己的见解,才算是真正理解了OO吧。。呵呵。。我也不太理解,说的不对的地方,还请见谅哦~~~~