【面向对象编程思想】- 什么是面向对象

面向对象的概念

要理解面向对象,首先需要了解什么是面向过程。面向过程的编程可以理解为 “记流水账” 的方式来写代码,也就是将大脑中对于一个业务的流程用代码来实现出来。因为流程化的内容很容易被大脑接受,所以面向过程的代码很容易实现,同时也容易被理解。

那面向对象有什么不同呢?面向对象的意思是在实现业务逻辑的时候,首先需要进行建模,也就是需要思考一下我来实现这个业务逻辑,需要新建哪些类。接着需要思考这些类之间如何关联起来,来实现整个业务逻辑。

面向对象的特性

在大学的课本中,一般是分为三个特性:封装,抽象和继承。

这里我理解的还应该多出一个概念“抽象”。下面分别对这四种特性先从表现上解释,再从意义上解释。

封装

表现

封装的表现主要体现在访问修饰符上,比如 private protected public,然后通过暴露出一些方法控制外部对象对自身对象属性的访问权限。

意义

隐藏了本类的信息,对访问本类的方法进行了保护,可以更加让调用方更加简单和安全地操作本类。

以手动挡汽车和自动挡汽车举例,手动挡汽车将换挡这个方法暴露出来供驾驶员使用,很显然如果是个新手,很容易因为操作不当导致汽车熄火。相反,自动挡汽车隐藏了换挡这个概念,对外只暴露 P R N D 四个档(当然不考虑有的汽车还有 S 档,有的 AT 变速箱也支持手动换挡)这样对新手来说,只需要控制汽车的前进后退的方向即可,不需要再考虑到底应该换哪个档,应该怎么踩离合器换挡等问题。

抽象

表现

面向接口编程,隐藏了方法的具体实现。

意义

调用方只需要知道有这个方法即可,不需要知道具体的实现。人脑承受系统的复杂度是有限的,抽象让人不需要关系具体实现,降低了系统的复杂度。

继承

表现

子类使用 extends 继承父类。

意义

提高了代码的复用性,可以将一些公用的方法提取到父类中或者抽象类中。
但是继承也不宜用多。超过 5 层的继承关系会让开发者很难理解,降低了代码的可读性。

多态

表现

使用父类对象引用子类对象。

意义

当需要改变代码逻辑的时候,只需要再写一个该类的另外一个实现类即可,体现了“开闭原则”(对修改关闭,对扩展开放)。

例如有一个上传文件的类叫做 FileUpload,此时我需要往阿里云上传文件,只需要实现一个 AliyunFileUpload。代码可以这样写: FileUpload fileUpload = new AliyunFileUpload() 。当我需要往腾讯云上传文件中,只要把代码改成 FileUpload fileUpload = new TencentFileUpload()

面向对象编程中容易遇到的问题

滥用 getter setter

相信大家都使用过 lombok 自动生成 getter setter 方法或者使用 IDE 一键生成 getter setter 的方式。

这种方式很方便,但是破坏了封装特性。对所有属性都生成了 public 的 getter 和 setter 方法,等于说任何对象都可以访问该类的所有 private 属性。那么这些属性被定义成 private 有什么意义呢?这会导致该类对外部暴露过多的方法,导致在使用在操作该类的数据时不安全。

尤其在开发时,使用 lombok,无法非常直观地查看 setter getter 在哪里被调用,导致在排查问题,或者修改方法时非常不方便。

为了避免这个问题,通常对于一个属性是否要暴露出 getter setter 方法需要思考,确定是否会对调用方的使用产生困扰和疑惑后,再决定是否需要暴露。这个思考过程,也是 “封装” 特性的体现。

滥用全局变量,全局方法

全局变量

一般我们会将常量定义在 Constants 类中,这样做的目的是避免使用 “魔法值”。但是如果不注意,Constants 类中的常量会越来越多,这样导致的问题是某个类只需要引入一个常量,但是 import 了这个 Constants 类后,引入了一堆无用的常量,整个类的编译速度降低了。

为了避免这个问题, 会将 Constants 类根据功能拆分。或者当一个类只需要特定几个常量值,可以直接定义本类中。

全局方法

一般我们会将通用的方法定义在 Utils 类中。这样做的目的是,将通用的方法提取到 Utils 类中,增加了代码的复用性。但是通常这样的方法是 static 修饰的,不符合面向对象的思想。

为了避免这个问题,面向对象的做法是将这些公共方法提取到父类中,使用 “继承” 的特性提高代码的复用性。当然,因为在 Java 中是单继承以及可能两个没什么继承关系的类需要提取公共方法时,这个时候别无选择,只能选择创建 Utils 类来解决,这个时候需要将 Utils 的功能进行拆解,避免某个 Utils 类过大。

面向过程的贫血模型

贫血模型通俗地说,这个类中的方法没有业务逻辑,只提供了 setter getter 方法。

这个很好理解,就是目前前后端分离 SSM 框架中的 Repository 层中的 DO 对象。该对象没有复杂的业务操作,只有对属性的 setter getter 方法。再往深了思考一层,其实这种贫血模型是将数据和操作分离,数据存储在了 DO 类中,数据操作则交给了 Service 这些类。

很明显,这个开发模型被广泛采用,因为处理简单业务的时候可以快速地解决问题,提高了开发地效率。但是面对复杂的业务场景时,Service 或者处理数据类的代码可能会很长很长,此时就需要基于面向对象的充血模型来解决问题了。充血模型在之后的篇幅中会提到。

发布了7 篇原创文章 · 获赞 0 · 访问量 55

猜你喜欢

转载自blog.csdn.net/m0_46857718/article/details/105431409