面向对象

之前零散的对于面向对象思想有一些思考,一直想总结成一篇文章,谈谈我对面向对象的理解。

概念

面向对象程序设计(英语:Object-oriented programming,缩写:OOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。它可能包含数据、属性、代码与方法。对象则指的是类的实例。它将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性,对象里的程序可以访问及经常修改对象相关连的数据。在面向对象程序编程里,计算机程序会被设计成彼此相关的对象。

使用面向对象方法和技术是为了更敏捷的响应客户需求,使得软件更易于维护和扩展。

对象和数据集合

OOP将对象作为程序的基本单元,一个对象包含了数据和方法。一个对象和一个数据的集合最主要的差别就是对象是有行为的,是有职责的。

理解面向对象的关键是不要将对象当作被操作的数据,对象是有自主行为的,是具有“生命”的。

边界与职责

面向对象主要思维特点是逻辑分析思维,认为万物皆有边界,如同世界这个词语一样,通过寻找边界封装定义一个事物,然后再探究这个事物内部的组成部分,通过封装不变性,开放变化性,增强系统的柔韧性和灵活性。

Understanding responsibilities is key to good object-oriented design” — Martin Fowler

理解职责是实现好的OOD的关键。面向对象是将职责通过方法纳入到对象中,和数据封装起来,形成一个有自主判断逻辑和基本逻辑的Actor

OOP 与 POP

面向对象诞生以来,面临着面向过程、面向数据和面向函数等范式的挑战,但是因为面向对象范式更接近人的思维和认识习惯,所以,使用OO实现业务建模设计,分析设计复杂的业务需求成为其主要强项。虽然随着Java等面向对象语言发展,将面向对象范式落地有形化,但也带来了对面向对象思想扭曲的理解,事件或消息驱动思想丰富拓展了现代面向对象思想。

面向对象和面向过程是也有本质区别的,面向过程只是根据CPU机器的执行时序去编程,而面向对象体现了软件工程师的专业水准。面向对象范式讲究的不只是编写出计算机能看懂的代码,也要编写出同类其他软件工程师能够看懂的代码,追求的不只是软件的功能,而是这些功能随着需求变化所具有的可维护性和可拓展性。

OOP的出现对POP确实存在很多颠覆性的,但并不能说POP已没有价值了,它们只是不同时代的产物,从方法论来讲,面向过程与面向对象看做是事物的两个方面–局部与整体(局部与整体是相对的),因此在实际应用中,两者方法都同样重要。

面向对象与面向数据库

由于很多程序员从一开始接受数据结构和算法的基础教育,导致思维方式偏功能化,虽然使用面向对象语言编程,但是编程思路还是面向过程和面向数据表的,面向对象思维和面向数据库思维主要区别是:前者以动态思维来看待事物,用对象概念封装对象内部属性状态和引起状态变化的行为方法;而后者以静态思维看待事物,只是记录事实的最后状态,并且混杂了具体数据库技术。

面向对象从软件的分析到设计及其编程单元测试,都已经有一套成熟可行的简便方案,可是我们由于接受传统滞后的教育原因,我们编程都只是从建立数据表结构开始,这种方式只适合小规模系统,当系统变大后,就需要重写,带来大量时间和金钱的浪费。而且习惯了面向过程和面向数据库的编程思维,要转变到面向对象思维上来,阻碍相当大,比登天还难,这就是现实中为什么大量都是基于数据库系统的原因。

SOLID-面向对象的设计原则

如何做面向对象设计?

  1. 抽象
  2. 职责
  3. 高内聚
  4. 松耦合

具体的SOLID原则是:SRP单一职责原则、OCP开闭原则、LSP里氏代换原则、ISP接口隔离原则和DIP依赖倒置原则。

每种原则含义见面向对象设计原则

OOP 与 AOP

随着软件规模的增大,应用的逐渐升级,慢慢地,OOP也开始暴露出一些问题。外围操作同样会在其他业务模块中出现,这样就会造成如下问题:

  • 代码混乱:核心业务模块可能需要兼顾处理其他不相干的业务外围操作,这些外围操作可能会混乱核心操作的代码,而且当外围模块有重大修改时也会影响到核心模块,这显然是不合理的。
  • 代码分散和冗余:同样的功能代码,在其他的模块几乎随处可见,导致代码分散并且冗余度高。
  • 代码质量低扩展难:由于不太相关的业务代码混杂在一起,无法专注核心业务代码,当进行类似无关业务扩展时又会直接涉及到核心业务的代码,导致拓展性低。

把日志、权限、事务、性能监测等外围业务看作单独的关注点(也可以理解为单独的模块),每个关注点都可以在需要它们的时刻及时被运用而且无需提前整合到核心模块中。每个关注点与核心业务模块分离,作为单独的功能,横切几个核心业务模块,这样的做的好处是显而易见的,每份功能代码不再单独入侵到核心业务类的代码中,即核心模块只需关注自己相关的业务,当需要外围业务(日志,权限,性能监测、事务控制)时,这些外围业务会通过一种特殊的技术自动应用到核心模块中。

所谓的特殊技术也就面向切面编程的实现技术,AOP的实现技术有多种,其中与Java无缝对接的是一种称为AspectJ的技术。

AOP的出现确实解决外围业务代码与核心业务代码分离的问题,但它并不会替代OOP,如果说OOP的出现是把编码问题进行模块化,那么AOP就是把涉及到众多模块的某一类问题进行统一管理。

面向对象与领域驱动设计

领域驱动设计将面向对象的理念进一步提升到了业务的层次,指导业务层面界限上下文的划分,指导业务层面不同模块的交互。两者思想类似但层次不同。

总结

面向对象的本质是逻辑分析哲学,现代逻辑学是面向对象的元语言。面向对象的核心就是将业务领域进行抽象、建模。

在面向对象设计过程中,我们就像是“造物主”,在创造每一种对象的时候,要“换位思考”,把自己当作是对象,想象自己如何与外界交互,以职责为中心,遵循SOLID原则进行建模设计。

参考资料

https://www.jdon.com/oo.html
https://blog.csdn.net/javazejian/article/details/56267036
https://zh.wikipedia.org/wiki/面向对象程序设计
https://www.jdon.com/designpatterns/ooprimer.html

Author: nopainanymore
Link: http://nopainanymore.me/Object-Oriented/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
wechat