VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Java教程 >
  • 面向对象程序设计概述

面向对象程序设计概述

面向对象程序设计(object-oriented programming,OOP)是当今主流的程序设计范型,它取代了20世纪70年代的“结构化”或过程式编程技术。由于Java是面向对象的,所以你必须熟悉OOP才能够很好地使用Java。

对象

面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。程序中的很多对象来自标准库,还有一些是自定义的。究竟是自己构造对象,还是从外界购买对象完全取决于开发项目的预算和时间。但是,从根本上说,只要对象能够满足要求,就不必关心其功能到底是如何实现的。

结构化程序设计

传统的结构化程序设计通过设计一系列的过程(即算法)来求解问题。一旦确定了这些过程,就要开始考虑存储数据的适当方式。这就是Pascal语言的设计者Niklaus Wirth将其著作命名为《算法+数据结构=程序》(Algorithms+Data
Structures=Programs,Prentice Hall,
1975)的原因。需要注意的是,在Wirth的这个书名中,算法是第一位的,数据结构第二位的,这就明确地表述了程序员的工作方式。首先要确定如何操作数据,然何组织数据的结构,以便于操作数据。而OOP却调换了这个次序,将数据放在第一位,然后再考虑操作数据的算法。

面对过程与面向对象的程序设计对比

对于一些规模较小的问题,将其分解为过程的开发方式比较理想。面向对象更加
适合解决规模较大的问题。要想实现一个简单的Web浏览器可能需要大约2000个过过程程,这些过程可能需要对一组全局数据进行操作。采用面向对象的设计风格,可能只据需要大约100个类,每个类平均包含20个方法(如图(面对过程与面向对象的程序设计对比)所示)。后者更易于程序员掌握,也容易找到bug。假设给定对象的数据出错了,在访问这个数据项的20个方法中查找错误要比在2000个过程中查找容易得多。

image

类的实例

类(class)是构造对象的模板或蓝图。我们可以将类想象成制作小甜饼的模具,将对象想象为小甜饼。由类构造(construct)对象的过程称为创建类的实例(instance)。

正如前面所看到的,用Java编写的所有代码都位于某个类里面。标准Java库提供了几千个类,可用于各种目的,如用户界面设计、日期、日历和网络编程。尽管如此,在Java中还是需要创建一些自己的类,以便描述你的应用程序所对应的问题领域中的对象。

封装

封装(encapsulation,有时称为数据隐藏)是处理对象的一个重要概念。从形式上看,封装就是将数据和行为组合在一个包中,并对对象的使用者隐藏具体的实现方式。

实例字段和方法

对象中的数据称为实例字段(instance
field),操作数据的过程称为方法(method)。作为一个类的实例,特定对象都有一组特定的实例字段值。这些值的集合就是这个对象的当前状态(state)。无论何时,只要在对象上调用一个方法,它的状态就有可能发生改变。

实现封装的关键在于,绝对不能让类中的方法直接访问其他类的实例字段。程序只能通过对象的方法与对象数据进行交互。封装给对象赋予了“黑盒”特征,这是提高重用性和可靠性的关键。这意味着一个类可以完全改变存储数据的方式,只要仍旧使用同样的方法操作数据,其他对象就不会知道也不用关心这个类所发生的变化。

Object类

OOP的另一个原则会让用户自定义Java类变得更为容易,这就是:可以通过扩展其他类来构建新类。事实上,在Java中,所有的类都源自一个“神通广大的超类”,它就是0bject。所有其他类都扩展自这个Object类。

继承

在扩展一个已有的类时,这个扩展后的新类具有被扩展的类的全部属性和方法。你只需要在新类中提供适用于这个新类的新方法和数据字段就可以了。通过扩展一个类来建立另外一个类的过程称为继承(inheritance)。

对象

对象的三个主要特性

要想使用OOP,一定要清楚对象的三个主要特性:

  • 对象的行为(behavior)——可以对对象完成哪些操作,或者可以对对象应用哪些方法?
  • 对象的状态(state)——当调用那些方法时,对象会如何响应?
  • 对象的标识(identity)——如何区分具有相同行为与状态的不同对象?

同一个类的所有对象实例,由于支持相同的行为而具有家族式的相似性。对象的行为是用可调用的方法来定义的。

此外,每个对象都保存着描述当前状况的信息。这就是对象的状态。对象的状态可能会随着时间而发生改变,但这种改变不会是自发的。对象状态的改变必须通过调用方法实现(如果不经过方法调用就可以改变对象状态,只能说明破坏了封装性)。

但是,对象的状态并不能完全描述一个对象。每个对象都有一个唯一的标识(identity,或称身份)。例如,在一个订单处理系统中,任何两个订单都存在着不同之处,即使所订购的货物完全相同,它们也是不同的订单。需要注意,作为同一个类的实例,每个对象的标识总是不同的,状态也往往存在着差异。

对象的这些关键特性会彼此相互影响。例如,对象的状态影响它的行为(如果一个订单“已送货”或“已付款”,就应该拒绝调用要求增删订单中商品的方法。反过来,如果订单是“空的”,即还没有预订任何商品,这个订单就不应该“送货”)。

识别类

传统的过程式程序中,必须从顶部的main函数开始编写程序。在面向对象程序设计时没有所谓的“顶部”。学习OOP的初学者因而常常会感觉无从下手。答案是:首先从识别类开始,然后再为各个类添加方法。

识别类的一个简单经验是在分析问题的过程中寻找名词,而方法对应着动词。

例如,在订单处理系统中,有这样一些名词:

  • 商品(Item);
  • 订单(Order);
  • 送货地址(Shipping address);
  • 付款(Payment);
  • 账户(Account)。

从这些名词就可以得到类Item、Order等。

接下来查看动词。商品被添加到订单中,订单会发货取消,另外可以对订单完成付款。对于每一个动词,如“添加”“发货”“取消”以及“完成付款”,都要识别出负责完成相应动作的对象。例如,当一个新的商品添加到订单中时,那个订单对象就是负责的对象,因为它知道如何存储商品以及如何对商品进行排序。也就是说,add应该是Order类的一个方法,它要取一个Item对象作为参数。

当然,这种“名词与动词”原则只是一种经验,在创建类的时候,只有经验才能帮助你确定哪些名词和动词重要。

类之间的关系

类的三种关系

在类之间,最常见的关系有

  • 依赖(“uses-a”);
  • 聚合(“has-a”);
  • 继承(“is-a”)。

依赖

依赖(dependence),即“uses-a”关系,是一种最明显的、最常见的关系。例如,Order类使用Account类是因为Order对象需要访问Account对象查看信用状态。但是Item类不依赖于Account类,因为Item对象不需要考虑客户账户。因此,如果一个类的方法使用或操纵另一个类的对象,我们就说一个类依赖于另一个类。

应该尽可能地将相互依赖的类减至最少。这里的关键是,如果类A不知道B的存在,它就不会关心B的任何改变(这意味着B的改变不会导致A产生任何bug)。用软件工程的术语来说,就是尽可能减少类之间的耦合

聚合

聚合(aggregation),即“has-a”关系,很容易理解,因为这种关系很具体。例如,一个Order对象包含一些Item对象。包容关系意味着类A的对象包含类B的对象。

注释

有些方法学家不喜欢聚合这个概念,而更加喜欢使用更一般的“关联”关系。
从建模的角度看,这是可以理解的。但对于程序员来说,“has-a”关系更加形象。我们喜欢使用聚合还有另一个原因:关联的标准记法不是很清楚,请参看表(表达类关系的UML符号)。

image

继承

继承(inheritance),即“is-a”关系,表示一个更特殊的类与一个更一般的类之间的关系。例如,Rushorder类由Order类继承而来。在更特殊的RushOrder类中包含了一些用于优先处理的特殊方法,还提供了一个计算运费的不同方法;而其他的方法,如添加商品、生成账单等都是从Order类继承来的。一般而言,如果类A扩展类B,类A不但包含从类B继承的方法,还会有一些额外的功能。

UML

很多程序员采用UML(Unified Modeling
Language,统一建模语言)绘制类图,用来描述类之间的关系。图(类图)就是这样一个例子。类用矩形表示,类之间的关系用带有各种修饰的箭头表示。表(表达类关系的UML符号)给出了UML中最常见的箭头样式。

image

 
出处:https://www.cnblogs.com/Huang-zihan/p/15183239.html


相关教程