设计模式学习笔记 - 面向对象 - 3.面向对象比面向过程有哪些优势?面向过程真的过时了吗?

简述

在过往的工作中,我发现很多人搞不清面向对象和面向过程的区别,总认为使用面向对象编程语言来开发,就是在面向面向对象编程了。而实际上,他们只是在用面向对象编程语言,编写面向过程风格的代码而已,并没有发挥面向对象编程的优势。这就相当于手握一把屠龙刀,却只把它当做一把普通的到来使用。


1.什么是面向过程编程与面向过程编程语言?

如果你是一名比较资深的程序员,最开始学习编程的时候接触的是 Basic、C等面向过程的编程语言,那么你对这两个概念肯定不陌生。但是如果你是新生代的程序员,一开始学习编程的时候,接触的就是面向对象编程语言,那你对这两个概念可能不熟悉。所以,在对比面向对象与面向过程优劣之前,我们先把面向过程编程和面向过程编程语言这两个概念搞清楚。

我们可以比对这面向对象编程和面向对象编程语言这两个概念来理解面向过程编程和面向过程编程语言。我们来回顾下面向对象编程和面向对象编程语言:

  • 面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态这四个特性,作为代码设计和实现的基石。
  • 面向对象编程语言支持类或对象的语法机制,能方便地实现面向对象编程四大特性的编程语言。

类比面向对象编程和面向对象编程语言的定义,对于面向过程编程和面向过程编程语言这个两个概念,我给出下面这样的定义。

  • 面向过程编程也是一种编程范式或编程风格。它以过程(可理解为方法、函数、操作)作为组织代码的基本单元,以数据(可理解为变量)与方法相分离为主要的特点。面向过程风格是一种流程化的编程风格,通过拼接一组顺序执行的方法来操作数据完成一项功能。
  • 面向过程编程语言首先是一种编程语言。它最大的特点是不支持类和对象这两个语法概念,不支持风格的面向对象编程特性,仅支持面向过程编程。

用一个例子来解释下。假设有一个记录了用户信息的文件 users.txt,每行文本的格式是 name&age&gender(如小王&28&男)。编写一个程序来逐行读取用户信息,然后格式化成 name,age,gender 这种格式,并且按照 age 从小达到排序后,重新写入另一个文件 formatted_user.txt。
首先,使用面向过程编程风格来编写这个程序,使用 C 语言来编写。

struct User {char name[64];int age;char gender[16];
}struct User parse_to_user(char* text) {// 将text“小王&28&男” 解析成结构体 struct User
}char* format_to_text(struct User user) {// 将结构体User格式化成文本 “小王,28,男”
}void sort_users_by_age(struct User users[]) {// 按照年龄从小到大排序users
}void format_user_file(char* file_path, char* new_file_path) {// 打开文件...struct User users[1024]; // 假设最大1024个用户int count = 0;while(1) {// 读取文件,直到读取结束// 从文件内读取一行内容...struct User user = parse_to_user(line);users[count++] = user;}sort_users_by_age(users);int i;for(i = 0; i < count; i++) {char* formatted_to_text = format_to_text(users[i]);// 写入formatted_to_text到文件...}// 关闭文件...
}int main(char ** args, int argv) {format_user_file("/file/user.txt", "/file/formatted_user.txt");
}

在看看面向对象这种风格编写出来的代码是什么样子的。

public class User {private String name;private int age;private String gender;public User(String name, int age, String gender) {this.name = name;this.age = age;this.gender = gender;}public static User parseFrom(String userInfoText) {// 将 “小王&28&男” 解析成类User}public String formatToText() {// 将类User转化成文本 “小王,28,男”}
}public class UserFileFormatter {public void format(String userFile, String formattedUserFile) {// 打开文件...List<User> users = new ArrayList<>();while (true) { // 读取文件,直到读取结束// 从文件内读取一行数据...User user = User.parseFrom(userInfoText);users.add(user);}// 按照年龄排序...for (int i = 0; i < users.size(); i++) {String formattedUserText = users.get(i).formatToText();// 写入到新文件...}// 关闭文件...}
}public class MainApplication {public static void main(String[] args) {UserFileFormatter userFileFormatter = new UserFileFormatter();userFileFormatter.format("/file/user.txt", "/file/formatted_user.txt");}
}

从上面代码,可以看出,面向过程和面向对象最近的区别是,代码的组织方式不同。面向过程风格的代码组织成立一组方法集合及其数据结构(struct User),方法和数据定义是分开的。而面向对象风格的代码被组织成一组类,方法和数据结构被绑定一起,定义在类中。

可能有人会觉得,上面这两个例子的面向对象编程和面向过程编程,这两个风格的区别貌似不是很大呀。

2.面向对象编程比面向过程编程有哪些优势?

为什么面向对象编程晚于面向过程编程出现,却能取而代之,称为主流的编程范式?面向对象编程和面向过程编程比起来,到底有哪些优势?

2.1 OOP 更加能够应对大规模复杂程序的开发

刚刚的例子,你可能感觉两种风格的代码貌似差不多,顶多就是代码组织方式有点区别,没有感觉到面向对象编程有什么优势。其实,主要原因就是因为这个例子比较简单、不够复杂。

对于简单的开发来说,不管是用面向过程编程风格,还是面向对象编程风格,差别确实不会很大,甚至有时候面向过程的编程风格反而更有优势。因为整个程序的处理流程只有一条主线,很容易被划分成顺序执行的几个步骤,然后逐句翻译成代码,这就非常适合采用面向过程这种面条式的编程风格来实现。

但是,对于大模型复杂程序的开发来说,整个程序的处理流程错综复杂,并非只有一条主线。如果把整个程序的处理流程画出来的话,会是一个网状结构。如果再用面向过程编程来实现,就会比较吃力了。这个时候,面向对象的编程风格的优势就比较明显了。

面向对象编程是以类为思考对象。在进行面向对象编程的时候,并不是一上来就去思考将流程拆为一个个方法,而是先去思考如何给业务建模,将需求翻译为类,如何给类之间建立交互关系,而完成这些工作完全不需要考虑错综复杂的处理流程。当有了类的设计之后,再像搭积木一样,按照处理流程将类组装起来形成整个程序。这种开发模式、思考问题的方式,能让我们在应对复杂程序开发的时候,思路更加清晰。

此外,面向对象编程还提供了一种更加清晰的、更加模块化的代码组织方式。比如,我们开发一个电商系统,业务逻辑发咋、代码量很大,可能要定义数百个函数、数百个数据结构,如何分门别类地组织这些函数和数据结构,才能看起来不至于凌乱呢?类就是一种非常好的组织这些函数和数据结构的方式,是一种将代码模块化的有效手段。

有人可能互说,像 C 语言这种面向过程的编程语言,也可以按照功能的不同,把函数和数据结构放到不同的文件里,以达到给函数和数据结构分类的目的。不过,面向对象编程本身提供了类的概念,强制你做这件事情,而面向过程编程并不强求。这也算是面向对象编程语言的一个小小的创新吧。

实际上,利用面向过程的编程语言照样可以写出面向对象风格的代码,只不过可能会比使用面向对象编程语言来说,付出的代码要高一些。而且,面向过程编程和面向对象编程并非完全对立。

2.2 OOP 风格的代码更易复用、易扩展、易维护

刚刚的例子比较简单,只用到了类、对象这两个基本的概念,并没有用到更加高级的四大特性。因此,面向对象编程的优势其实并没有发挥出来。

面向对象编程提供的封装、抽象、继承、多态这些特性,能极大地满足复杂的编程需求,能方便我们写出更易复用、易扩展、易维护的代码。

  • 首先,封装特性将数据和方法绑定在一起,通过访问权限控制,只允许外部调用者通过类暴露的有限方法访问数据,而不会像面向过程那样,数据可以被任意访问和修改。因此,面向对象编程提供的封装特性更有利于提高代码的易维护性
  • 其次,再看下抽象特性。我们知道,函数本身就是一种抽象,它隐藏了具体的实现。在使用函数的时候,只需要了解函数具体有什么功能,而不需要了解它是怎么实现的。从这一点上,不管面向对象编程,还是面向过程编程,都支持抽象特性。不管,面对对象编程还提供了其他抽象特性的实现方式,这些实现方式是面向过程所不具备的,比如基于接口实现的抽象。基于接口的抽象,可以让我们在不改变原有实现的情况下,轻松替换新的实现逻辑,提高带代码的可扩展性
  • 接着,继承特性是面向对象编程相比于面向过程编程所特有的两个特性之一(另一个是多态)。如果两个类有一些相同的属性和方法,我们就可以将这些相同的代码,抽取到父类中,让两个子类继承父类。这样两个子类也可以重用父类中的代码,避免了代付重复多谢,提高了代码的复用性
  • 最后,在看下多态这个特性。基于这个特性,我们在需要修改一个功能实现的时候,可以通过实现一个新的子类的方式,在子类中重写原来的功能逻辑,用子类代替父类。在实际的代码运行过程中,调用子类新的功能逻辑,而不是在原有代码上做修改。这就遵从了“对修改关闭、对扩展开放”的设计原则,提高了代码的可扩展性。除此之外,利用多态特性,不同的类对象可以传递相同的方法,执行不提供的代码逻辑,提高了代码的复用性

所以所,基于四大特性,利用面向对象编程,我们可以更轻松地写出易复用、易扩展、易维护的代码。

2.3 OOP 语言更加人性化、更加高级、更加智能

人类最早和计算机打交道是通过 0、1 这样的二进制指令,然后是汇编语言,再之后才出现了高级编程语言。在高级编程语言中,面向过程编程语言又早于面向对象编程语言出现。之所以先出现面向过程编程语言,那是因为和及其的交互方式,从二进制指令、汇编语言到面向过程编程语言,是一个非常自然的过渡,是一种流程化的、面条式的编程风格,用一组指令顺序操作数据,来完成一项任务。

从指令到汇编再到面向过程编程语言,跟机器打交道的方式在不停地进化,让人和机器打交道越来越容易。面向对象编程语言的出现,也顺应了这样的发展规律,也就是说,面向对象编程语言比面向过程编程语言更加高级。

面向对象编程语言是一种人类的思维方式,在进行面向对象编程的时候,我们在思考如何给业务建模,如何将真实的世界映射为类或对象,这让我们更加聚焦到业务本身,而不是思考如何跟机器打交道。

越高级的编程语言,离机器越远,离人类越近,也越智能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/701603.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

目标跟踪之KCF详解

High-Speed Tracking with Kernelized Correlation Filters 使用内核化相关滤波器进行高速跟踪 大多数现代跟踪器的核心组件是判别分类器&#xff0c;其任务是区分目标和周围环境。为了应对自然图像变化&#xff0c;此分类器通常使用平移和缩放的样本补丁进行训练。此类样本集…

目标检测新SOTA:YOLOv9 问世,新架构让传统卷积重焕生机

在目标检测领域&#xff0c;YOLOv9 实现了一代更比一代强&#xff0c;利用新架构和方法让传统卷积在参数利用率方面胜过了深度卷积。 继 2023 年 1 月 YOLOv8 正式发布一年多以后&#xff0c;YOLOv9 终于来了&#xff01; 我们知道&#xff0c;YOLO 是一种基于图像全局信息进行…

YoloV8改进策略:主干网络改进|MogaNet——高效的多阶门控聚合网络

文章目录 摘要1、简介2、相关工作2.1、视觉Transformers2.2、ViT时代的卷积网络3、从多阶博弈论交互的角度看表示瓶颈4、方法论4.1、MogaNet概述4.2、多阶门控聚合4.3、通过通道聚合进行多阶特征重新分配4.4、实现细节5、实验5.1、ImageNet分类5.2、密集预测任务5.3、消融实验和…

Linux信号详解

文章目录 一、Linux信号1. 信号的概念2. 信号的定义3. 系统定义的信号 二、信号产生的方式1.通过键盘产生2. 通过系统调用3. 软件条件4. 硬件异常 三、信号处理函数1. OS发送信号的实质2. 指令发送信号3. signal()4. sigaction() 四、信号屏蔽机制1. 信号处理方式2.信号集操作函…

更改QTabWidget的选项卡的位置

选项卡位置函数&#xff1a; QTabWidget::setTabPosition(QTabWidget::North); //默认为上面 上北下南 参数&#xff1a; QTabWidget::North //上面 QTabWidget::South); //下面 QTabWidget::West //左侧 QTabWidget::East)//右侧 选项卡外观函数&#xff1a; QTabWidget::setT…

【0267】pg内核初始化 process table(ProcGlobal、PROC_HDR、PGPROC)

1. 前言 在postmaster或standalone后端启动期间初始化全局进程表(global process table)。该过程由InitProcGlobal()完成,对于此函数: (1)还创建了支持所请求的后端数量所需的所有每个进程信号量。我们过去只在后端真正启动时才分配信号量,但这很糟糕,因为它会让Postg…

nodejs+vue+ElementUi废品废弃资源回收系统

系统主要是以后台管理员管理为主。管理员需要先登录系统然后才可以使用本系统&#xff0c;管理员可以对系统用户管理、用户信息管理、回收站点管理、站点分类管理、站点分类管理、留言板管理、系统管理进行添加、查询、修改、删除&#xff0c;以保障废弃资源回收系统系统的正常…

Qt_纯虚函数的信号和槽

简介 在C中&#xff0c;纯虚函数是一个在基类中声明但没有实现的虚函数。纯虚函数的声明以 “ 0” 结尾。纯虚函数的目的是为了提供一个接口&#xff0c;但是不提供实现。派生类必须实现纯虚函数&#xff0c;否则它也会成为一个抽象类。纯虚函数可以在基类中定义&#xff0c;也…

unity驱动3d模特跳舞 穿模问题 穿透

是的&#xff0c;这个问题在3D建模和动画领域通常被称为“穿模”&#xff08;Clipping&#xff09;或“穿透”&#xff08;Penetration&#xff09;。更具体 用unity驱动3d模特跳舞&#xff0c;手会穿过衣服 当使用Unity驱动3D模特跳舞时&#xff0c;手部穿过衣服的问题通常是…

python中的类与对象(1)

目录 一. 引子&#xff1a;模板 二. 面向过程与面向对象 &#xff08;1&#xff09;面向过程编程 &#xff08;2&#xff09;面向对象编程 三. 对象与类 &#xff08;1&#xff09;对象 &#xff08;2&#xff09;类 四. 面向对象程序设计的特点&#xff1a;封装&#…

[c++] 记录一次引用使用不当导致的 bug

在工作中看到了如下代码&#xff0c;代码基于 std::thread 封装了一个 Thread 类。Thread 封装了业务开发中常用的接口&#xff0c;比如设置调度策略&#xff0c;设置优先级&#xff0c;设置线程名。如下代码删去了不必要的代码&#xff0c;只保留能说明问题的代码。从代码实现…

【C语言】linux内核ipoib模块 - ipoib_ib_handle_rx_wc

一、中文注释 // 定义一个处理InfiniBand接收完成工作请求的函数 static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) {// 通过网络设备获取私有数据结构struct ipoib_dev_priv *priv ipoib_priv(dev);// 获取工作请求ID&#xff0c;并屏蔽掉接收…

探索未来:Web3如何改变我们的生活方式

在数字化的时代&#xff0c;技术的不断发展和创新已经成为了我们生活的常态。而在这个不断变革的过程中&#xff0c;区块链技术作为一种颠覆性的技术&#xff0c;正逐渐成为人们关注的焦点。作为区块链技术的下一代&#xff0c;Web3正日益崭露头角&#xff0c;成为了未来的发展…

橘子学es原理01之准备工作

es本身是具备很好的使用特性的&#xff0c;我指的是他的部署方面的&#xff0c;至于后期的使用和运维那还是很一眼难尽的。 我们从这一篇开始就着重于es的一些原理性的的一些探讨&#xff0c;当然我们也会有一些操作性的&#xff0c;业务性的会分为多个栏目来写。比如前面我写的…

Flutter开发进阶之Package

Flutter开发进阶之Package 通常我们在Flutter开发中需要将部分功能与整体项目隔离&#xff0c;一般有两种方案Plugin和Package&#xff0c;Application是作为主体项目&#xff0c;Module是作为原生项目接入Flutter模块。 当独立模块不需要与原生项目通讯只需要Plugin就可以&a…

【广度优先搜索】【网格】【割点】1263. 推箱子

作者推荐 视频算法专题 涉及知识点 广度优先搜索 网格 割点 并集查找 LeetCode:1263. 推箱子 「推箱子」是一款风靡全球的益智小游戏&#xff0c;玩家需要将箱子推到仓库中的目标位置。 游戏地图用大小为 m x n 的网格 grid 表示&#xff0c;其中每个元素可以是墙、地板或…

计算几何相关算法汇总

目录 1 专题说明2 算法参考 1 专题说明 本专题用来记录计算几何相关算法&#xff0c;包括&#xff1a; 求两个矩形的交集。 2 算法 算法&#xff1a;求两个矩形的交集 C实现&#xff0c; // 定义矩形结构体 struct Rectangle {int x1, y1; // 左下角坐标int x2, y2; // 右…

利用LaTex批量将eps转pdf、png转eps、eps转png、eps转svg、pdf转eps

1、eps转pdf 直接使用epstopdf命令&#xff08;texlive、mitex自带&#xff09;。 在cmd中进入到eps矢量图片的目录&#xff0c;使用下面的命令&#xff1a; for %f in (*.eps) do epstopdf "%f" 下面是plt保存eps代码&#xff1a; import matplotlib.pyplot as…

javafx环境搭建

参考链接 使用上述参考搭建javafx环境。

ABC342A-E题解

文章目录 A题目AC Code&#xff1a; B题目AC Code&#xff1a; C题目AC Code&#xff1a; D题目AC Code&#xff1a; E题目AC Code: A 题目 这个 A 题为什么是平时 B 题的分值&#xff1f; 统计每一个字母的出现次数&#xff0c;找到出现次数为 1 1 1 的字母&#xff0c;输…