谈谈面向对象 之 抽象

原创 2013年12月09日 08:45:43

一、引言

上一篇博客谈了面向对象的基本概念,从这篇开始,聊聊面向对象的几个特征:抽象、封装、继承、多态。我们先拿抽象这一特征开刀。

不止一位同事将抽象这一特征排除在外,认为面向对象有三个特征。这让我感到意外,因为,抽象是面向对象最为重要的特征。对象本身的状态与行为,以及对象之间的关系,都是抽象的结果。没有抽象,就没有对象,也就谈不上面向对象了。因此,抽象是面向对象的第一特征。

那么,都抽象什么呢?

二、抽象的内容

广泛流传的说法是,相比于面向过程,面向对象的优势在于将问题空间和解空间统一起来。在面向过程的时代,问题空间(现实世界)中是对象,解空间(设计、代码)中是过程,两者不一致,需要来回切换,能把人的精神搞分裂。而到了面向对象的时代,问题空间和解空间要处理的都是对象,这样开发系统就顺畅多了。

这样的说辞带有严重的学究气,但说明了一个问题,认为系统中的对象是从现实世界中的对象转换而来的,这种转换是提取其相关属性,摒弃无关属性。换句话说,也就是抽象。想要高端大气上档次,不妨称之为现实客体的静态映像。但这只是抽象的内容之一,

2.1 现实客体的静态映像

这种抽象,对于要处理的客观对象,在系统中也构造相应的对象。提取其中需要关注的属性,而摒弃那些无关的属性。

这是最为简单的抽象,因为其在现实世界中可见,因而容易理解,抽象程度也就比较低。很多菜鸟谈到抽象这一特征时,往往指的是这一点。

例如,现实世界中有用户,我们就抽象出 User 这一对象类,我们关注的属性,如用户名,登陆账号,密码,联系方式等等,都提取过来。而无关的属性,如长相,穿衣习惯,政治面貌,等等,则置之不理。

以能源管理系统为例,装置,介质,管网,节点,等等,既是现实世界中的对象,也是系统中的对象。

深入到我们在做的这个系统的内部看看,有很多对象的抽象只到了这一层面。看看这些对象的类定义,我们会看到他们有共同的特征:类的内容主要是抽象过来的那些属性,方法很少。这种对象称为POJO(Java)或POCO(.NET)。

他们都是初步抽象的产物,还不成熟,等待长大。

2.2 行为封装

属性是对象的状态。对象不仅仅有状态,还有行为。对象幼小时,能做的事很少,也就是行为很少。其成长的重要标志,是职责增加,行为增加。也就是方法的增加。

因此,抽象的第二个层面,是对象行为的抽象。

仅抽象对象的状态,将行为独立于对象,仍然是 程序 = 数据结构 + 算法 的思维,是面向过程的思维。

将和对象紧密耦合的过程,赋予对象,成为其方法,即将处理逻辑封装到对象内,这就是行为抽象。

例如,对于用户,我们需要检查其是否通过认证,是否通过鉴权,这都可以成为其方法。对于装置,获取投入、产出、损失、能源消耗等,也是其方法。

一个真正能用于解决实际业务问题的系统中,对象方法个数往往会超过其属性的个数。

2.3 行为提炼

将行为中相同或相似的部分提炼出来,定义为公共的行为,是设计和开发的重要表现。这种行为的提炼,往往被我们的开发者所忽视。

我们做了一个报表工具,要累加指定期间内各个时间段的量,时间段有不同的类型,如日、旬、月、季、年等。例如,指定期间 1月1日到4月30日,如果时间段类型是日,对于这四个月的120天,取每天的量累加起来,如果时间段类型为月,则对于这四个月,取每月的量累加起来。

我们的程序员最初是这样做的:

decimal sum = 0;

if (periodType == PeriodType.日)
{
    for (DateTime dt = StartTime; dt <= EndTime; dt = dt.AddDays(1))
    {
        sum += GetData(dt, Period.日);
    }
}
else if (periodType == PeriodType.月)
{
    for (DateTime dt = StartTime; dt <= EndTime; dt = dt.AddMonths(1))
    {
        sum += GetData(dt, Period.月);
    }
}
else ...

在实际代码中,这个 if else 的序列相当长,求值累加的逻辑也不像这里只有一行,因而显得重复而冗长。

这里的问题表现为缺少提炼:可以将这个过程抽象为,针对给定的时间序列,累加序列上各个时间点的值:

decimal sum = 0;

foreach (DateTime dt in GetTimeSeries(BeginTime, EndTime, periodType))
{
    sum += GetData(dt, periodType);
}

(如果用resharper,它会提醒你有更简便的表示。)


至于计算时间序列,就是一个很容易处理的问题了。

对行为的提炼,不仅仅限于对象的方法,也适用于其他过程化开发。

在以前做的一个项目中,需要计算各个装置的单位能耗:单位能耗 = 能耗量 / 加工量,这个是在Oracle中用存储过程实现的。问题在于,各个装置的能耗量和加工量的计算方法大致相同,但不完全一样。我们一个兄弟,就为每一套装置,分别写了一套能耗量和加工量的计算逻辑。那是在燕山石化,一百多套装置啊,他那个Package写了一万多行。后来需求不停地变啊,一旦有一点变动,他就要调到半夜。就这样,生生把自己逼离职了。后来我们做了重构,对计算方法做了分类整理,采用通用的计算方法,将不同之处通过加配置来项处理,将一万多行的PL/SQL,变成了一千多行。

2.4 非现实对象的出现

让问题空间和解空间中都是对象,就认为天下太平了,真是 very simple, sometimes naive,这严重低估了系统的复杂性。

问题空间和解空间中确实都是对象,但从需求分析阶段(当然得是面向对象分析)开始,两个空间中的对象就不一样了,随着项目的进展,这种区别会越来越大:解空间中会出现现实世界中不曾有过的对象,这样的对象越来越多。

例如,用户管理中,角色这样的对象,是分析过程中抽象出来的。

更常见的例子是设计模式中出现的那些类,诸如策略、状态、XxxImp之类。更不用说各种抽象类和接口了。

这种无中生有,是进一步抽象的结果。这也更进一步促进了行为的抽象:将合适的行为抽象到新的类中。

2.5 类结构提炼

一些类的集合,形成一种较为固定的结构,完成特定的功能。例如设计模式,例如MVC这样的Paradigm,由多个类组成,但比架构小。这种抽象,提炼出了类的状态、类的行为,更重要的是类与类之间的关系。

在我们的项目中也可以找出类似的例子。我们用NPOI将一个二进制格式的Excel文档,转换为Excel 2003 XML格式的文档。我们把这个转换抽象为树复制,Excel的内容可以看作一棵树:根节点是Workbook,下面是若干Sheet,下面是若干Row,等等。XML天然是一棵树。有了这个抽象,就可以利用树的特性,后面的实现就是如何转换各类节点的细节问题了。

3、抽象是一种思维习惯

用喊口号的方式结束吧:面向对象不仅仅是一种技术,而是一种方法论。与此类似,抽象不仅仅是上述几类动作,而是一种思维习惯。它不是面向对象的专属,而可以用于任何开发场合。






相关文章推荐

深入Java系列——面向对象之(一)——抽象

此次对于java的学习,可谓是很轻松的一个过渡。在软考过程中不知不觉就和她成为好盆友了。从之前的VB、C#、 C++基础学习,到现在的java,一个感受就是编程语言大概都是一样的,无非都是指挥机器按照...

面向对象地本质-抽象

   什么是面向对象的本质?近日在阅读一位网友在CSDN博客上发表的文章,作者认为对象,对象的职责,以及对象之间的交互构成了OO思想的本质。在我看来,抽象更接近OO思想的本质。我是从以下几点考虑的:1...
  • houdy
  • houdy
  • 2006年06月07日 20:28
  • 3654

面向对象编程之抽象

面向对象编程 公司投资没有了,人们陆续都离职了,正好可以抽出个时间看看书,C++ Primer第四版,以前粗略的读过一遍,但是一直感觉好多地方就那么过去了,读书这个事情就是这样,每读一遍,都能有许多新...

面向对象最重要的是“抽象”,三层最重要的也是“抽象”,没有抽象就不是真正的面向对象、三层。

    只用class的,那叫做“基于对象”,比如当初的vb6.0;只是分了三个项目,把以前写在一起的代码分成了三份,所谓的业务逻辑层就是一个传声筒,这一类自称三层的,在我看来都是“模仿三层”,...
  • jyk
  • jyk
  • 2010年05月01日 13:08
  • 8099

面向对象—抽象

面向对象分析与设计的主要任务是,找出类和对象,构建对象模型。 对象模型的主要要素:抽象、封装、模块化与层次结构。 对象模型的次要要素:类型、并发、持久。 抽象描述了一个对象的基本特征...

面向对象程序设计具有4个共同特征:抽象性、封装性、继承性和多态性

面向对象程序设计具有4个共同特征:抽象性、封装性、继承性和多态性

抽象的概念,对象的概念,面向对象和面向过程的区别

1.什么是抽象 抽象就是把一个对象的分析出各个属性,来代替表达的手法 抽就是分离,象就是表示出来的部分 比如说把一个学生对象抽象一下,就剩下他的一些属性和行为,例如姓名,性别,年龄,身高,学习的...

面向对象需求分析——用例图和活动图

面向对象软件开发的方法有:a,面向对象分析(OOA)b,面向对象设计(OOD)c,面向对象实现(00I)d,面向对象测试(OOT),e,面向对象维护(OOM)这几个主要大步骤。下边我们就从面向对象的角...

关于面向对象以及三大特征的解释

第一次写,想想就有点小激动。个人理解有不全的地方

第八节 面向对象——抽象,多态

  • 2016年05月29日 12:29
  • 591KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:谈谈面向对象 之 抽象
举报原因:
原因补充:

(最多只允许输入30个字)