1. 面向过程编程和面向过程编程语言
1.1. 定义
面向过程编程:以过程(可以理解为方法、函数、操作)作为组织代码的基本单元,以数据(可以理解为成员变量、属性)与方法相分离为最主要的特点。面向过程风格是一种流程化的编程风格,通过拼接一组顺序执行的方法来操作数据完成一项功能。
面向过程编程语言:不支持类和对象两个语法概念,不支持丰富的面向对象编程特性(比如继承、多态、封装),仅支持面向过程编程。
2. 两种编程范式的不同点
- 开发方式不同:OOP 以类和对象为思考对象,考虑如何给业务建模,如何将需求翻译成类,如何建立类之间的交互关系。而完成这些工作完全不要考虑错综复杂的处理流程。类的分析和设计完成之后再按照流程实现整个程序,POP 思考如何将复杂的流程拆解为一个个方法,然后按照顺序执行的步骤进行代码设计
- 应用场景不同:OOP 适合大规模复杂程序的开发,POP 适合业务逻辑简单,流程单一的程序开发。大规模复杂程序的特点,整个程序的处理流程错综复杂,把整个程序的处理流程画出来的话,会是一个网状结构
- 出现时间不同:OOP 晚于 POP 出现,顺应时代的需求,相比于 POP,OOP 提供了更多的特性,比如四大特性,通过类组织函数和数据结构更容易进行代码模块化的设计并且结合四大特性,更方便开发者写出易复用、易扩展、易维护的代码。
总的来说:
- 面向过程编程是计算机思维方式,即:如何设计一组指令,告诉机器去执行这组指令,操作某些数据,帮我们完成某个任务
- 而面向对象编程思考如何给业务建模,如何将真实的世界映射为类或者对象,这让我们更加能聚焦到业务本身,而不是思考如何跟机器打交道
3. 避免面向对象编程退化成面向过程编程
3.1. 滥用Getter、Setter方法
解决办法:
- Getter 针对集合对象,集合数据容易被外部修改。
- 返回拷贝对象
- Collections.unmodifiableList()
- Setter 提供给外部随意更改数据的方法。
- 尽量不要给属性提供 Setter 方法
- 根据业务需要选择提供
3.2. 滥用全局变量和全局方法
常量类 Constants
缺点:
- 一旦内容变多可维护性差,且难以查找修改需要的常量
- 被很多类依赖,每次修改 Constants 会导致程序重新编译增加编译时间,降低开发效率
- 影响代码的复用性,如果其他服务需要就要把整个类迁过去
解决办法:
- 将 Constants 类拆解为功能更加单一的多个类
- 不单独设计 Constants 类,而是将变量定义到使用变量的类中
Utils 类
为什么要设计 Utils 类: A 类 和 B 类不具有继承关系,但有相同的代码逻辑,为了代码复用,将其抽象到 Utils 类中成为一个静态方法
缺点:
方法与数据分离是完完全全的面向过程编程
解决方案:
- 如果相同的代码逻辑可有抽象到其他类(前提是业务相关联)
- 功能细化,拆解成功能更加单一的类
在 Java 中什么叫全局变量和全局方法:
- 全局变量:单例类对象、静态成员变量和常量(常量类)
- 全局方法:静态方法
3.3. 定义数据和方法分离的类
基于贫血模型的开发模式
传统的 MVC 三层架构开发方案就是典型的贫血模型开发方式,这种方式下业务逻辑方法都被定义在 Controller、Service和Repository中,而数据则放在 Entity 和 DTO 中。
缺点:
强依赖 SQL(业务逻辑都被封装在 SQL 中),且就算业务逻辑只有一点改动,也需要新写一条 SQL,SQL 语句难以复用
解决方案:
采用基于充血模型 DDD 领域驱动开发(前提是业务很复杂,否则没有效果)
4. 如何正确的在 OOP 中使用 POP
最终目的还是写出易维护、易读、易复用、易扩展的高质量代码
只要我们能避免 POP 风格的一些弊端,控制好它的副作用,在掌控范围内为我们所用,我们就大可不用避讳在面向对象编程中写面向过程风格的代码。