4.1 面向对象程序设计概述

4.1 面向对象程序设计概述

面向对象程序设计(objected-oriented programming,OOP)是当今主流的程序设计范型,它取代了20世纪70年代的“结构化”或过程式编程技术。由于Java面向对象的,所以你必须熟悉OOP才能很好的使用Java。
面向对象的程序是由对象组成的,每个对象包含对用户公开的特定功能部分和隐藏的实现部分。程序中的很多对象来自标准库,还有一些是自定义的。究竟是自己构造对象,还是从外界购买对象完全取决于开发项目的预算和时间。但是,从根本上说,只要对象能够满足要求,就不必关心其功能到底是如何实现的。
传统的结构化设计通过设计一系列的过程(算法)来求解问题,一旦确定了这些过程,就要开始考虑存储数据的适当方式。这就是Pascal语言的设计者Niklaus 将其著作命名为《算法+数据结构=程序》的原因。需要注意的是,在这个书名中,算法是第一位的,数据结构是第二位的,这就明确地表述了程序员的工作方式。首先,要确定如何操作数据,然后再决定如何组织数据的结构,以便于操作数据。而OOP却调换了这个次序,将数据放在了第一位,然后再考虑操作数据的算法。
对于一些规模较小的问题,将其分解为过程的开发方式比较理想。面向对象更加适合较大规模的问题。要想实现一个简单的web浏览器可能需要大约2000个过程,这些过程可能需要对一组全局数据进行操作。采用面向对象的设计风格,可能需要大约100个类,每个类平均20个方法。后者更易于程序员掌握,容易找到bug。假设给定对象的数据出错了,在访问对象的20个方法中寻找错误比在2000个方法中寻找错误要容易得多。

4.1.1 类

类(class)是构造对象的模板或蓝图。我们可以将类想象成制作小甜饼的模具,将对象想象成小甜饼。由类构造(construct)对象的过程称为创建类的实例(instance)。
正如前面所看到的,用Java编写的所有代码都位于某个类中。标准Java库提供了几千个类,可用于各种目的,如用户界面设计、日期、日历和网络编程。尽管如此,在Java中还是要创建一些自己的类,以便描述你的应用程序对应的问题领域中的对象。
封装(encapsulation),有时也叫数据隐藏,是处理对象的一个重要概念。从形式上看,封装就是将数据和行为组合在一个包中,并对对象的使用者隐藏具体的实现细节。对象中的数据称为实例字段(instance field),操作数据的过程称为方法(method)。作为一个类的实例,特定对象都有一组特定的实例字段值。这些值的集合就是这个对象的当前状态(state)。无论何时,只要在对象上调用一个方法,它的状态就有可能发生改变。
实现封装的关键在于,绝对不能让类中的方法直接访问其他类的实例字段。程序只能通过对象的方法与对象数据进行交互。封装给对象赋予了“黑盒”特征,这是提高重用性和可靠性的关键。这意味着一个类可以完全改变存储数据的方式,只要仍旧使用同样的方法操作数据,其他对象就不会知道也不用关心这个类所发生的变化。
OOP的另一个原则会让用户自定义Java类变得更为容易,这就是:可以通过扩展其他类来构建新类。事实上,在Java中,所有的类都源自一个“神通广大的超类”,他就是Object。所有其他类都扩展自这个Object类。在下一章中,你会看到Object类的详细介绍。
在扩展一已有的类时,这个扩展后的新类具有被扩展类的全部属性和方法。你只需要在新类中提供适用于这个新类的新方法和数据字段就可可以了。通过扩展一个类来建立另外一个类的过程称为继承(inheritance),有关继承的详细内容请参看下一章。

4.1.2 对象

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

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

同一个类的所有对象实例,由于支持相同的行为而具有家族式的相似性。对象的行为是用可调用的方法来定义的。
此外,每个对象都保存着描述当前状况的信息。这就是对象的状态。对象的状态可能会随着时间而发生改变,但这种改变不会是自发的。对象状态的改变必须通过调用方法实现。(如果不经过方法调用就可以改变对象状态,只能说明破坏了封装性)。
但是,对象的状态并不能完全描述一个对象。每个对象都有一个唯一的标识。例如,在一个订单系统中,任何两个订单都存在着不同之处,即使所订购的货物完全相同,他们也是不同的订单。注意,作为通过一个类的实例,每个对象的标识总是不同的,状态也往往存在差异。
对象的这些关键特性往往会彼此影响。例如,对象的状态影响它的行为。(如果一个订单已送货或者已付款,就应该拒绝增删订单中商品的方法。反过来,如果订单是空的,这个订单就不该被发货。)

4.1.3 识别类

传统的过程式程序中,必须从顶部的main函数开始编写程序。在面向对对象程序的设计中,没有所谓的顶部。首先从识别类开始,然后再为各个类添加方法。
识别类的一个简单经验是在分析问题的时候寻找名词,而方法则是动词
例如,在订单处理系统中,有这些名词:

  • 商品
  • 订单
  • 送货地址
  • 付款
  • 账户
    这些名词就可以作为一个类。

接下来寻找动词。商品被添加到订单中,订单会发货取消,另外可以对订单完成付款。对于每一个动词,要确认完成这个动作的对象是哪一个对象。例如,当一个新的商品添加到订单时,这里的订单对象就是动作的完成者。就是说,add()应该是订单类的一个方法,add方法需要一个商品对象作为参数。
这种寻找名词和动词的方法只是一种经验。创建类的时候,只有真正的实战经验才能帮助你确定那些名词和动词重要。

4.1.4 类之间的关系

类之间常见的关系有:依赖(uses-a),聚合(has-a),继承(is-a)。
依赖,是最明显,最常见的关系。例如,订单类使用账户类是因为订单对象需要访问账户对象查看信用状态。但是,商品类不依赖于账户类,因为商品对象不需要考虑客户账户。因此,如果一个类的方法使用或者操纵另一个类的对象,我们就说一个类依赖于另一个类。
应该尽可能的减少依赖关系。这里的关键,如果一个类不知道另一个类的存在,它压根儿就不会关心另一个类的改变。
聚合。例如,一个订单对象包含一些商品对象。聚合,意味着一个类的对象包含另一个类的对象。
继承,表示一个更特殊的类与一个更一般的类之间的关系。如果类A扩展类B,类A不但包含从类B继承的方法,还会有一些额外的功能。
可以使用UML(统一建模语言)绘制类图,来描述类之间的关系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值