001第1章 对象导论1.1抽象过程、1.2每个对象都有一个接口、1.3每个对象都提供服务

    xiaoxiao2022-07-04  156

    1.1 抽象过程 OOP允许根据问题来描述问题,而不是根据计算机来描述问题。 五个基本特性:万物皆对象、程序是对象的集合、可发送消息、可分类class、可替代性(substitutability是OOP中最强有力的概念之一) 。 对象具有状态、行为和标识。 1.2 每个对象都有一个接口 银行出纳员问题 在程序执行期间具有不同的状态而其他方面都相似的对象会被分组到对象的类中,这就是关键字class的由来。创建抽象数据类型类是面向对象程序设计的基本概念之一。 我们在面向对象程序设计中实际上进行的是创建新的数据类型,但事实上所有的面向对象程序设计语言都使用class这个关键词来表示数据类型。因为类描述了具有相同特性(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型。 OOP的应用确实可以将大量的问题很容易地降解为一个简单的解决方案。 事实上,面向对象程序设计的挑战之一, 就是在问题空间的元素和解空间的对象之间创建一对一的映射。 接口确定了对某一特定对象所能发出的请求。但是,在程序中必须有满足这些请求的代码。 向某个对象“发送消息”(产生请求),这个对象便知道此消息的目的,然后执行对应的程序代码。 UML(Unified Modelling. Language 统一建模语言) 1.3 每个对象都提供服务 当试图开发或理解~,最好的方法之一就是将对象想像为“服务提供者“。 将对象看作是服务提供者还有一个附带的好处:它有助于提高对象的内聚性。 高内聚是软件设计的基本质量要求之一:这意味着一个软件构件(例如一个对象,当然它也有可能是指一个方法或一个对象库)的各个方面“组合”得很好。 在良好的面向对象设计中,每个对象都可以很好地完成一项任务,但是它并不试图做更多的事。 将对象作为服务提供者看待是一件伟大的简化工具。

    文章目录

    1.1 抽象过程1.2 每个对象都有一个接口1.3 每个对象都提供服务 下为原书原文

    1.1 抽象过程

    所有编程语言都提供抽象机制。 可以认为,人们所能够解决的问题的复杂性直接取决于抽象的类型和质量。 机器模型(位于“解空间“内,这是你对问题建模的地方,例如计算机) 实际待解问题的模型(位于“问题空间“ 内, 这是问题存在的地方,例如一项业务)

    面向对象方式通过向程序员提供表示问题空间中的元素的工具而更进了一步。 这种表示方式非常通用,使得程序员不会受限于任何特定类型的问题。 我们将问题空间中的元素及其在解空间中的表示称为对象。 (你还需要一些无法类比为问题空间元素的对象。) 这种思想的实质是程序可以通过添加新类型的对象使自身适用于某个特定问题。 OOP允许根据问题来描述问题,而不是根据运行解决方案的计算机来描述问题。 Alan Kay 总结了Smalltalk的五个基本特性,这些特性表现了一种纯粹的面向对象程序设计方式: 1)万物皆为对象。将对象视为奇特的变量,它可以存储数据,除此之外, 你还可以要求它,在自身上执行操作。 理论上讲,你可以抽取待求解问题的任何概念化构件(狗、建筑物、服务等),将其表示为程序中的对象。 2)程序是对象的集合,它们通过发送消息来告知彼此所要做的。要想请求一个对象,就必须对该对象发送一条消息。 更具体地说,可以把消息想像为对某个特定对象的方法的调用请求。 3)每个对象都有自己的由其他对象所构成的存储。换句话说,可以通过创建包含现有对象的包的方式来创建新类型的对象。 因此,可以在程序中构建复杂的体系,同时将其复杂性隐藏在对象的简单性背后。 4)每个对象都拥有其类型。按照通用的说法,“每个对象都是某个类(class)的一个实例(instance)”,这里“类”就是“类型”的同义词。 每个类最重要的区别于其他类的特性就是“可以发送什么样的消息给它”。 5)某一特定类型的所有对象都可以接收同样的消息。 这种可替代性 (substitutability) 是OOP中最强有力的概念之一。

    Booch对对象提出了一个更加简洁的描述:对象具有状态、行为和标识。 这意味着每一个对象都可以拥有内部数据(它们给出了该对象的状态)和方法(它们产生行为),并且每一个对象都可以唯一地与其他对象区分开来,具体说来,就是每一个对象在内存中都有一个唯一的地址。

    1.2 每个对象都有一个接口

    所有的对象都是唯一的,但同时也是具有相同的特性和行为的对象所归属的类的一部分。 这种思想被直接应用千第一个面向对象语言Simula-67, 它在程序中使用基本关键字class来引入新的类型。

    Simula就像其名字一样,是为了开发诸如经典的银行出纳员问题(bank teller problem)这样的仿真程序而创建的。 在银行出纳员问题中,有出纳、客户、账户、交易和货币单位等许多“对象”。 在程序执行期间具有不同的状态而其他方面都相似的对象会被分组到对象的类中,这就是关键字class的由来。 创建抽象数据类型(类)是面向对象程序设计的基本概念之一。 抽象数据类型的运行方式与内置(built-in)类型几乎完全一致:你可以创建某一类型的变址(按照面向对象的说法,称其为对象或实例),然后操作这些变量(称其为发送消息或请求;发送消息,对象就知道要做什么)。 每个类的成员或元素都具有某种共性:每个账户都有结余金额,每个出纳都可以处理存款诮求等。 同时,每个成员都有其自身的状态:每个账户都有不同的结余金额,每个出纳都有自己的姓名。 因此,出纳、客户、账户、交易等都可以在计算机程序中被表示成唯一的实体。 这些实体就是对象,每一个对象都属于定义了特性和行为的某个特定的类。

    所以,尽管我们在面向对象程序设计中实际上进行的是创建新的数据类型,但事实上所有的面向对象程序设计语言都使用class这个关键词来表示数据类型。 当看到类型一词时,可将其作为类来考虑,反之亦然。

    因为类描述了具有相同特性(数据元素)和行为(功能)的对象集合,所以一个类实际上就是一个数据类型,例如所有浮点型数字具有相同的特性和行为集合。 二者的差异在于,程序员通过定义类来适应问题,而不再被迫只能使用现有的用来表示机器中的存储单元的数据类型。 可以根据需求,通过添加新的数据类型来扩展编程语言。 编程系统欣然接受新的类,并且像对待内置类型一样地照管它们和进行类型检查。 面向对象方法并不是仅局限于构建仿真程序。 无论你是否赞成以下观点,即任何程序都是你所设计的系统的一种仿真,面向对象技术的应用确实可以将大量的问题很容易地降解为一个简单的解决方案。

    一旦类被建立,就可以随心所欲地创建类的任意个对象,然后去操作它们,就像它们是存在于你的待求解问题中的元素一样。 事实上,面向对象程序设计的挑战之一, 就是在问题空间的元素和解空间的对象之间创建一对一的映射。

    接口确定了对某一特定对象所能发出的请求。但是,在程序中必须有满足这些请求的代码。 这些代码与隐藏的数据一起构成了实现。从过程型编程的观点来看, 这并不太复杂。 在类型中,每一个可能的请求都有一个方法与之相关联,当向对象发送请求时,与之相关联的方法就会被调用。 此过程通常被概括为:向某个对象“发送消息”(产生请求),这个对象便知道此消息的目的,然后执行对应的程序代码。

    为了向对象发送消息,需要声明对象的名称,并以圆点符号连接一个消息请求。 从预定义类的用户观点来看,这些差不多就是用对象来进行设计的全部。

    前面的图是UML(Unified Modelling Language 统一建模语言)形式的图,每个类都用一个方框表示,类名在方框的顶部, 你所关心的任何数据成员都描述在方框的中间部分,方法(隶属于此对象的、用来接收你发给此对象的消息的函数)在方框的底部。 通常,只有类名和公共方法被示于UML设计图中,因此,方框的中部就像本例一样并未给出。 如果只对类型感兴趣,那么方框的底部甚至也不需要给出。

    1.3 每个对象都提供服务

    当正在试图开发或理解一个程序设计时,最好的方法之一就是将对象想像为“服务提供者”。 程序本身将向用户提供服务,它将通过调用其他对象提供的服务来实现这一目的。 你的目标就是去创建(或者最好是在现有代码库中寻找)能够提供理想的服务来解决问题的一系列对象。

    着手从事这件事的一种方式就是问一下自己:“如果我可以将问题从表象中抽取出来,那么什么样的对象可以马上解决我的问题呢?” 例如,假设你正在创建一个簿记系统,那么可以想像,系统应该具有某些包括了预定义的簿记输入屏幕的对象,一个执行簿记计算的对象集合,以及一个处理在不同的打印机上打印支票和开发禀的对象。 也许上述对象中的某些已经存在,但是对于那些并不存在的对象,它们看起来像什么样子?它们能够提供哪些服务?它们需要哪些对象才能履行它们的义务? 如果持续这样做,那么最终你会说“那个对象看起来很简单,可以坐下来写代码了”,或者会说“我肯定那个对象已经存在了"。 这是将问题分解为对象集合的一种合理方式。

    将对象看作是服务提供者还有一个附带的好处:它有助于提高对象的内聚性。 高内聚是软件设计的基本质量要求之一:这意味着一个软件构件(例如一个对象,当然它也有可能是指一个方法或一个对象库)的各个方面“组合”得很好。 人们在设计对象时所面临的一个问题是,将过多的功能都塞在一个对象中。 例如,在检查打印模式的模块中,你可以这样设计一个对象,让它了解所有的格式和打印技术。 你可能会发现,这些功能对于一个对象来说太多了,你需要的是三个甚至更多个对象, 其中,一个对象可以是所有可能的支票排版的目录,它可以被用来查询有关如何打印一张支票的信息; 另一个对象(或对象集合)可以是一个通用的打印接口,它知道有关所有不同类型的打印机的信息(但是不包含任何有关簿记的内容,它更应该是一个需要购买而不是自己编写的对象); 第三个对象通过调用另外两个对象的服务来完成打印任务。 这样,每个对象都有一个它所能提供服务的内聚的集合。 在良好的面向对象设计中,每个对象都可以很好地完成一项任务,但是它并不试图做更多的事。 就像在这里看到的,不仅允许通过购买获得某些对象(打印机接口对象),而且还可以创建能够在别处复用的新对象(支票排版目录对象)。

    将对象作为服务提供者看待是一件伟大的简化工具,这不仅在设计过程中非常有用,而且当其他人试图理解你的代码或重用某个对象时,如果他们看出了这个对象所能提供的服务的价值,它会使调整对象以适应其设计的过程变得简单得多。

    最新回复(0)