首先来看看结构化的软件开发方法
1、结构化的软件开发方法
SASD方法,也可称为面向功能的软件开发方法或者面向数据流的软件开发方法。SASD方法是20世纪80年代使用最广泛的软件开发方法。它首先用结构化分析(Structure Analysis,SA)对软件进行需求分析,然后用结构化设计(Structure Design,SD)方法进行总体设计,最后进行结构化编程(Structure Programming,SP)。这种开发方法使得开发步骤明确,SA、SD和SP相辅相成,一气呵成。
结构化开发方法主要按照功能来划分软件的结构,它把软件系统的功能看做是根据给定的输入数据,进行相应的运算,然后输出结果,
进行结构化设计时,首先考虑整个软件系统的功能,然后按照模块划分的一些基本原则(比如内聚性和松耦合)等,对功能进行分解,把整个软件系统划分成多个模块,每个模块实现特定的子功能。为了提高软件的内聚性,在模块中还会把功能分解到更小的子模块中。在完成了所有的模块设计后,把这些模块拼装起来,就构成了整个软件系统。软件系统可看做是多个子系统的集合,每个子系统都具有输入输出的功能模块。
结构化设计是属于自顶向下的设计,在设计阶段就不得不考虑如何实现系统的功能,因为分解功能的过程其实就是实现功能的过程。结构化设计的局限性在于不能灵活地适应用户不断变化的需求。当用户需求发生变化,就需要自顶向下地修改模块的结构,有时候甚至整个软件系统的设计被完全推翻。
缺点:
A、自顶向下地按照功能来划分软件模块。软件的功能不是一成不变的,会随着用户需求的变化而改变,这使得软件在设计阶段就难以设计出稳定的系统结构。
B、软件系统中最小的子系统是方法。方法和一部分与之相关的数据分离,全局变量数据和常量数据分散在系统的各个角落,这削弱了各个系统之间的相对独立性,从而影响了软件的可维护性。
2、面向对象的软件开发方法简介
面向对象的开发方法把软件系统看成各种对象的集合,对象就是最小的子系统,一组相关的对象能够组合成更复杂的子系统。面向对象的开发方法具有以下优点。
A、把软件系统看成各种对象的集合,这更接近人类的自然思维方式。
B、软件需求的变动往往是功能的变动,而功能的执行者--对象一般不会有大的变化。这使得按照对象设计出来的系统结构比较稳定。
C、对象包括属性(数据)和行为(方法),对象把数据及方法的具体实现方式一起封装起来,这使得方法和与之相关的数据不再分离,提高了每个子系统的相对独立性,从而提高了软件的可维护性。
D、支持封装、抽象、继承和多态,提高了软件的可重用性、可维护性和可扩展性。
2.1、对象模型
在面向对象的分析和设计阶段,致力于建立模拟问题领域的对象模型。建立对象模型既包括自底向上的抽象过程,也包括自顶向下的分解过程。
(1)、自底向上的抽象
建立对象模型的第一步是从问题领域的陈述入手。分析需求的过程与对象模型的形成过程一致,开发人员与用户的交谈是从用户熟悉的问题领域中的事物(具体实例)开始的,这就使用户与开发人员之间有了共同语言,使得开发人员能彻底搞清用户需求,然后再建立正确的对象模型。开发人员需要进行以下自底向上的抽象思维。
A、把问题领域中的事物抽象为具体特定属性和行为的对象。
B、把具有相同属性和行为的对象抽象为类。
C、若多个类之间存在一些共性(具有相同属性和行为),把这些共性抽象到父类中。
在自底向上的抽象过程中,为使子类能更合理地继承父类的属性和行为,可能需要自顶向下的修改,从而使整个类体系更加合理。由于这种类体系的构造是从具体到抽象,再从抽象到具体,符合人类的思维规律,因此能更快、更方便地完成任务。这与自顶向下的结构化开发方法构成鲜明对照。
(2)、自顶向下的分解
在建立对象模型的过程中,也包括自顶向下的分解。例如对于计算机系统,首先识别出主机对象、显示器对象、键盘对象和打印机对象等。接着对这些对象再进一步分解,例如主机对象有处理器对象、内存对象、硬盘对象和主板对象等组成。
2.2、UML可视化建模语言
面向对象的分析与设计方法中概念和流派思想各不相同,需要用一种统一的符号来描述在软件分析和设计阶段勾画出来的对象模型,UML(Unified Modeling Language,统一建模语言)应运而生。UML是一种定义良好、易于表达、功能强大且普遍适用的可视化建模语言。它吸取了诸多流派的优点,而且又进一步地发展,最终成为大众所共同接受的标准建模语言。
2.3、Rational Rose可视化建模工具
Rational Rose 是Rational公司开发的一种可视化建模工具,它采用UML语言来构建对象模型,是分析和设计面向对象软件系统的强有力的工具。
3、面向对象开发中的核心思想和概念
在面向对象的软件开发过程中,开发者的主要任务就是先建立模拟问题领域的对象模型,然后通过程序代码来实现对象模型。到底如何建立对象模型,如何用程序代码实现对象模型,并且能保证软件系统的可重用性、可扩展性和可维护性呢?这不是两三句话就能回答清楚的问题.
3.1、问题领域、对象、属性、状态、行为、方法、实现
问题领域是指软件系统所模拟的真实世界中的系统。随着计算机技术的发展和普及,软件系统渗透到社会的各个方面,几乎可用来模拟任意一种问题领域,对象是对问题领域中事物的抽象。对象具有如下特性:
A、万物皆为对象。
B、每个对象都是唯一的。对象的唯一性来自于真实世界中事物的唯一性。
C、对象具有属性和行为。对象的行为包括具有的功能及具体的实现。在建立对象的模型阶段,仅仅关注对象有什么样的功能,而不需要考虑如何实现这些功能。
D、对象具有状态。状态是指某个瞬间对象的各个属性的取值。
E、对象都属于某个类,每个对象都是某个类的实例。
3.2、类、类型
类是一组具有相同属性和行为的对象的抽象。类及类的关系构成了对象模型的主要内容。如1-9图所示,对象模型用来模拟问题了领域,Java程序实现对象模型,Java程序运行在Java虚拟机提供的运行时环境中,Java虚拟机运行在计算机上。
面向对象编程的主要任务就是定义对象模型中的各个类。
3.3、消息、服务
软件系统的复杂功能是由各种对象协同工作来共同完成的。这种协作关系通过发送消息来实现,对象提供的服务是由对象的方法来实现的,因此发生消息实际上也就是调用一个对象的方法。
3.4、接口
既然每个对象都是服务提供者,如何对外提供服务呢?对象通过接口对外提供服务。在现实世界中,接口也是实体,比如电源插口、洗衣机上的按钮和电灯的开关。而在面向对象的范畴中,接口是一个抽象的概念,是指系统对外提供的所有服务。系统的接口描述系统能够提供哪些服务,但是不包含服务的实现细节。
接口是提高系统之间松耦合的有力手段。
在Java语言中,接口有两种意思:
A、一是指以上介绍的概念性的接口,即指系统对外提供的所有服务,在对象中表现为public类型的方法的声明。
B、二是指用interface关键字定义的实实在在的接口,也称为接口类型,它用于明确地描述系统对外提供的所有服务,它能够更加清晰的把系统的实现细节与接口分离。
3.5、封装、透明
封装是指隐藏对象的属性和实现细节,仅仅对外公开接口。封装能为软件系统带来以下优点。
(1)便于使用者正确、方便地理解和使用系统,防止使用者错误修改系统的属性。还是以供电系统为例,过去房屋墙壁的上方都是电线,现在的房屋里电线都“不见”了,在墙壁上只露出了一些电源插口。为什么要把电线藏起来呢?理由很简单,暴露在外面的电线不安全也不美观。
(2)有助于建立各个系统之间的松耦合关系,提高系统的独立性。当某一个系统的实现发生变化时,只要它的接口不变,就不会影响到其他的系统。
(3)提供软件的可重用性,每个系统都是一个相对独立的整体,可以在多种环境中得到重用。例如,干电池就是一个可重用的独立系统,在相机、手电筒、电动剃须刀和玩具等中都能发挥作用。
(4)降低了构建大型系统的风险,即使整个系统不成功,个别的独立子系统有可能依然是有价值的。
一个设计良好的系统会封装所有的实现细节,把它的接口与实现清晰地隔离开来,系统之间只通过接口进行通信。面向对象的编程语言主要通过访问控制机制来进行封装,这种机制能控制对象的属性和方法的可访问性。
对封装提出两大原则:
(1)、把尽可能多的东西藏起来,对外提供简捷的接口
系统的封装程度越高,那么它的相对独立性就越高,而且使用起来也更方便。
(2)、把所有的属性藏起来
假如某种属性允许外界访问,那么提供访问该属性的公开方法。为什么不把属性定义为public类型,让使用者直接访问呢?这样做有以下原因:
A、更符合真实世界中外因通过内因起作用的客观规律。一个对象的属性发生变化应该是外因和内因共同作用的结果。
B、能够灵活的控制属性的读和修改的访问级别。
C、防止使用者错误地修改属性。如修改口令时,要求口令必须是6位数,在setPassword()中很容易实现这段逻辑。
D、有助于对象封装实现细节。
与封装具有相同含义的一个概念就是透明。
3.6、抽象
抽象是指从特定角度出发,从已经存在的一些事物中抽取我们所关注的特性,形成一个新的事物的思维过程。抽象是一种由具体到抽象、由复杂到简洁的思维方式。在面向对象的开发过程中,抽象体现在以下方面
1、从问题领域的事物到软件模型中的对象的抽象
在建立对象模型时,分析问题领域中的实体,把它抽象为对象。真实世界中的事物往往有多种多样的属性,应该根据事物所处的问题领域来抽象出具有特定属性的对象。
2、从对象到类的抽象
在建立对象模型时,把具有相同属性和功能的对象抽象为类。
3、从子类到父类的抽象
当一些类之间具有相同的属性和功能时,把这部分属性和功能抽象到一个父类中。从子类到父类的抽象有两种情况:
- 不同子类之间具有相同的功能时,并且功能的实现方式也完全一样。例如自行车和三轮车的父类为非机动车类。自行车和三轮车都有刹车功能,并且实现方式也一样。这种情况下,把这个功能放在父类即非机动车类中实现,子类不必要重复实现这个功能。提供代码的可重用性和可维护性。
- 不同子类之间具有相同的功能,但功能的实现方式不一样。例如日光灯和电灯都能照明,但是实现方法不一样。这种情况下,父类即照明设施类中仅仅申明这种功能,但不提供具体的实现。这种抽象方法与面向对象的多态性相结合,有助于提高子系统之间的松耦合性。
在java语言中,抽象有两种意思:
- 当抽象作为动词时,就是上述的抽象思维过程。
- 当抽象作为形容词时,可以用来修饰类和方法。若一个方法被abstract修饰,则表明这个方法没有具体的实现;若一个类被abstract修饰,则表明这个类不能被实例化,例如把日光灯类和电灯类都抽象为父类--照明设施类Lighting。Lighting类是个抽象类,它的light()方法是个抽象方法,仅仅描述了Lighting类具有的功能,但没有被实现,只有它的子类的light()方法才能被实现。
3.7、继承、扩展、覆盖
在父类和子类之间同时存在着继承和扩展关系。子类继承了父类的属性和方法,同时,子类中还可以扩展出新的属性和方法,并且还可以覆盖父类中方法的实现方式。覆盖也是专用术语,是指在子类中重新实现父类中的方法。