什么是面向对象编程OOP

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


相对于 “一个程序只是一些函数的集合,或简单的计算机指令列表。”的传统软件设计观念而言,面向对象编程可以看作是使用一系列对象相互协作的软件设计。 在 OOP 中,每个对象能够接收消息,处理数据和发送消息给其他对象。每个对象都可以被看作是一个拥有清晰角色或责任的独立小机器。


对于面向对象,狭义地来说,我们说基于OO语言的Class和Object就是面向对象编程,广义地来说,传统的进程, 微服务中的服务, Actor框架中的Actor何尝不也是对象呢,同样是提供接口行为和管理属于自己的状态数据,只有上升到这个层面的理解,你可以才能更好地理解OO到底是解决什么问题,也不会被OO这个范式给约束住。


典型的面向对象语言包括:Java, C++, C#, Python, PHP, Ruby, Perl, Object Pascal, Swift, Scala和Smalltalk等。


面向对象究竟要解决什么问题


编码的本质其实就是层次化分解与重新组合的过程。对于程序的组合而言, 什么样的代码才是更好的: 代码的表面积必须要比它们的体积增长的更为缓慢。(几何对象的表面积是以尺寸的平方的速度增长的,而体积是以尺寸的立方的速度增长的,因此表面积的增长速度小于体积。)

代码块的表面积是是我们复合代码块时所需要的信息。代码块的体积 是我们为了实现它们所需要的信息。一旦代码块的实现过程结束,我们就可以忘掉它的实现细节,只关心它与其他代码块的相互影响。在面向对象编程中,类或接口的声明就是表面。在函数式编程中,函数的声明就是表面。

(上述请参加《函数式编程与面向对象编程[5]:编程的本质》)


怎样才能做到表面积增长速度小于体积增长速度?当然是分解,信息隐藏,抽象。而这些也正是面向对象所追求和擅长的。

面向对象主要目的是为了模块化。 软件工业最近20年来,能够构建如此大规模的需求频繁变化的软件系统,很大程度上得益于面向对象对于模块化的良好支持。而现在风头正劲的微服务化,无非是把模块化的思想,从进程内模块(类),变为进程间而已。


面向对象不是目的,而是手段


面向对象三大特征:封装,继承和多态, 这是很多程序员都知道的概念,但是很多人对于OO的理解仅局限于此,并且把这个作为面向对象编程的目的了。


封装,就是为了隐藏信息,减少模块与模块之间的耦合,达到高内聚低耦合。

继承,就是为了复用代码,分离单一变化方向,并且提供多态的基础支撑。

多态,就是为了解决算法的变化问题,并且与继承一起提供归一化接口,实现面向接口编程,提供可重用性。


而这一切都是为了追求高内聚低耦合,也就是模块的局部化影响,这也是软件设计的目的,只有真正意识到自己的追求,那么也就不会有面向对象,面向函数或者面向过程编程的争论了,都是为了模块化,更好地管理软件的复杂性,其他的都是手段或者工具。没有一种工具可以包打天下,解决具体的问题,使用最合适的手段,才是我们程序员应该追求的。如果以为你有一个锤子,就把所有东西都当成钉子,这明显是不对的。


模块设计中的原则和模式


我们前面讲到复杂系统要更好维护,那么一定就需要进行模块化。所谓模块化,就是将系统划分为子系统,子系统划分为若干模块,大模块划分为小模块的过程。 模块划分的目的主要是降低系统的开发难度,增加系统的可维护性等。


那么如何衡量模块的划分的好与坏,那么就是内聚和耦合。我们要追求的是高内聚和低耦合,保持模块的局部化影响。


那么如何实现模块的高内聚低耦合,Thoughtworks袁英杰提出的正交四原则是一个很好的方法,具有很强的指导性和操作性。SOLID的原则也是可以很好引导我们如何进行软件模块设计。


软件设计模式(比如Gof的23中设计模式)是帮助界定了软件系统中各个构建以及它们之间的相互关系。模式代表了在一个特定下有关设计的巧妙的解决办法,是值得我们去学习和遵循的,这样不用重复浪费时间,也可以进行通用的概念的交流。


无论我们采用什么样的架构模式、软件设计模式, 都要为了高内聚低耦合的目标而服务(如果某些DFX设计需要打破这些原则,需要进行tradeoff)。通过熟练使用前面这些原则和模式,可以有效地帮助我们进行模块化设计。


总结


整个OO训练营大讲堂已经完结了,我们在这个过程中讲解了面向对象的基本概念,正交设计,演进式设计,TDD等,而这一切都是为了软件的模块化设计, 这些也只是软件设计的入门知识,大家在后续的工作中还需要掌握架构设计与模式,领域驱动设计等解决复杂系统的设计和实现方法。 我希望大家通过十节课的学习真的了解了软件设计的目的:长期范围内更容易应对变化,不要忘记模块的高内聚低耦合原则, 结合实现的成本收益比进行软件实现方案的选择,最终实现简单的易扩展的软件系统。


上一篇:[Java] 入门(03)


下一篇:理解POP、OOP、AOP编程