面向对象编程的误解
我觉得大多数程序员都理解错了。这里的大多数不限于Java程序员,而是指使用面向对象编程语言的大多数程序员。本人就是其中一个。
最根本的原因在于,我们把面向对象里的“对象”理解错了,我们理解成了语法层面的对象。所以我们的代码才会出现所谓的贫血模型。
面向对象编程里的“对象”是什么?
封装了数据和行为的东西
我们的代码有体现吗?
没有。语法层面对象的3大特点(封装、继承、多态),我们的代码都有体现。
但是对象里要么是只有数据,没有行为(POJO)。要么是只有行为,没有数据(Serivce)。即所谓的贫血模型。
定义POJO,封装了属性和getter&setter,看似具有封装性,其实仅仅是一个数据容器而已。因为没有把数据和行为封装起来,行为都放在Service里了。
这就是我说的语法层面的面向对象。正式的叫法是面向数据编程。
真正的面向对象,面向的是生活中的真实对象,用代码的方式模拟真实的对象,即我们说的模型:
比如我们要模拟猫这个现实中的对象。我们了解到猫有品种、颜色、体重等属性;猫有吃鱼、捕鼠的行为。
那么首先对它进行建模。这个模型要能如实的反应猫的特点,并且这个模型是稳定的,一旦定了不能随意修改,比如随便的将“捕鼠”这个行为拿掉。
注意这里说的是模型,该模型里有数据,有行为。真正用代码实现模型的是不一定只有一个类。可能有很多个类:聚合根,实体,值对象,域服务等。
这些类合起来称作模型!
注意这个点,这些类合起来称作模型!虽然有些类可能只有行为,没有数据(比如域服务),但这不能称作贫血。因为贫血指的是模型,而不是单个类。
网上有很多关于贫血的讨论,有些说法已经跑偏了,他们认为只要某个类没有同时具备数据和行为就是贫血的。或者实体里没有实现持久化就是贫血的。
这种看法是短视的。站在模型的角度从上往下看,实体,值对象,域服务,(实现持久化的)在一个模块里紧密联系,协同合作,就相当于封装了数据和行为,
这就不贫血了。
理解了上述的“面向数据”和“贫血”这2个概念,才算是领悟到了“面向对象”的真谛。