您的位置:首页 > 其它

谈谈面向对象

2013-11-22 22:36 190 查看

一、为什么要说这个话题?

我们搞软件的,对于“面向对象”这个词,都听到过无数遍。这是一个非常非常非常老旧的话题。想说一下这个话题,主要是受到几件事情的触动:

在参加面试时,问到对“面向对象”概念的理解,我们的面试官所期待的标准答案往往是,说出封装、继承、多态这三个特征,以及它们的含义。特别是多态的含义;
在一次架构师培训时,讲师谈到自己对“面向对象”的体会,说体会最深的是封装这一个特性,封装就是好呀!
最重要的是,我们现在实现的系统,虽然用的语言是C#,但几乎静态方法一路到底,或者相当于静态方法一路到底。

这都让我认为,虽然“面向对象”是一个非常非常非常老旧的话题,但对它的理解还很难说得上到位。有谈谈的必要。

二、“面向对象”是什么?

随着面向对象在程序设计领域大行其道,它也逐步入侵到软件开发的其它领域:面向对象分析、面向对象设计、面向对象数据库,我还见过面向提对象测试的。在这些领域中,除了在数据库领域败给关系技术外,面向对象所向披靡。

那么,面向对象到底是什么,是需求分析技术,软件设计技术,还是程序编码技术?都是。但这些技术背后,应该有一种共通的东西。这种共通的东西,应用到不同的领域,就表现为不同的技术。所谓“天地有正气,杂然赋流形。下则为河岳,上则为日星。”那么,这种共通的东西是什么?

我认为是一种方法论,面向对象归根结蒂是一种方法论。下面是对于面向对象的谭氏定义:

面向对象是描述和构建系统的方法论,该方法论认为,一个系统由相互作用的对象组成,对象的状态决定了系统的状态,对象的行为决定了系统的行为。对象是通过抽象得到的,一个对象是对相关状态和行为的封装,继承是对象之间一种重要的关系,对象的行为往往是多态的。

这个定义兼顾了分析、设计和开发。其中分析是在描述一个系统,设计和开发则是在构建系统。其核心在于,指出一个系统是由相互作用的对象组成的。我们在开发一个系统时,应该满脑子想的都是对象,将注意力集中到对象上:如何提炼对象,如何定义对象的状态和行为,如何建立对象之间的关系,如何创建和销毁对象,等等。

说句题外话。在名字上,“面向对象”翻译得有点不妥,不能很好地反映原文“Object Oriented”的含义。我曾听到两个台湾同行聊天,取笑我们的翻译:“你知道什么是‘面向对象’吗?原来就是‘物件导向’呀,哈哈哈!”我觉得他们确实有理由取笑,“物件导向”确实更为贴切,更能反映出原意。“面向对象”用做微博上的一个程序员征婚活动的名字,倒是更合适一些。

三、“伪面向对象”的表现

面向对象是一种方法论,不采用这种方法论指导行动,即便利用了面向对象的工具,如利用C#、Java这样的面向对象语言进行开发,也不一定是真正的面向对象,我们不妨称之为“伪面向对象”。

“伪面向对象”是面向过程的思维方式导致的。我们知道,面向对象是为了克服面向过程的缺点发展起来的,如果仍然使用面向过程的思维,自然就做不好面向对象。

那么具体表现是什么?最为突出的有两点。

提出第一点之前先说一段经历。老谭曾经管理过一个开发小组,用的开发语言是C++。但是我注意到小组中有一位,仍然在用C进行开发,没有利用C++中面向对象的任何特征。这和团队的风格不一致,我要求她(真的是她啊)利用C++重构。刚过了半天,这位神人就说重构好了,已经改为C++了。我一看,确实在用C++,因为定义了类,所有方法都放到了类中。但和没用C++几乎没有区别,仅仅是在类上加了一个static关键字而已。

所以,“伪面向对象”的第一点表现是,虽然定义了类,但逻辑是,或者主要是由静态方法实现的。

在这种情况下,基本上没有有效提炼对象,自然就谈不上真正的面向对象。

使用静态方法,不一定表现为在方法前面加上了static关键字。有些没有static关键字的方法,其实质上仍然是静态方法。

我们目前的项目就是合适的例子。该项目的技术架构,分为展现层、服务接口层、业务逻辑层、数据访问层。从服务层开始,均通过接口向上层提供服务,而每层服务的实现,有不少是在一个方法中通过调用下层的接口完成。

例如,服务接口层提供获取管网的服务,定义了接口:

public interface ICommonService
{
......
EnergyNet GetEnergeNet(long netId);
......
}

并予以实现:

public class CommonService : ICommonService
{
private ICommonServiceImp imp;

......
public EnergyNet GetEnergeNet(long netId)
{
return imp.GetEnergyNet(netId);
}
......
}

自然,业务逻辑层也提供了接口,并予以实现:

public interface ICommonServiceImp
{
......
EnergyNet GetEnergyNet(long netId);
......
}


public class CommonServiceImp : ICommonServiceImp
{
private ICommonDao commonDao;
......
public EnergyNet GetEnergyNet(long netId)
{
return commonDao.GetEnergyNet(netId);
}
......
}
同样的故事也发生在数据访问层上。

这样的实现有两个特点:

所定义的类仅用于实现接口,如类CommonService仅用于实现接口ICommonService;
类方法中没有创建其它对象。

对于这种实现,如果不是因为接口实现的关系,这些类和静态类是相当的,自然其中的方法也相当于静态方法。

“伪面向对象”的第二点表现是,长方法。一般我们将一个方法控制在20行内。富含业务逻辑的方法如果超过了50行,往往意味着程序员正在用过程化的思路处理问题,而没有抽象出必要的对象。在真正面向对象的方法中,会将复杂的业务逻辑分解到合适的对象中,原来的长方法也就分解为不同对象的多个短方法。

四、未完待续

这里我们从总体上描述了面向对象这一概念。老谭计划对面向对象的特征,即抽象、封装、继承、多态,一一进行剖析。但愿有精力和时间。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: