为什么面向对象编程逐渐取代了面向过程编程了呢

那么就可能需要我们去了解什么是面向过程编程,不用去深入的学习,只是了解其概念

很多人很多时候,使用面向对象编程语言,却写出了面向过程的代码,没法发挥面向对象编程的优势,

那么为了搞懂面向对象和面向过程的区别,可以进行如下的对比

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

2.面向对象相比于面向过程,优势何在

3.为什么说面向对象编程语言比面向过程高级

4.怎么区分面向对象和面向过程语言

5.在面向对象编程中,为什么容易写出面向过程的代码

6.面向过程的未来何在

那么我们一一讲解

1.什么是面向过程编程,或者面向过程编程语言

实际上,我们可以拿面向对象编程和面向对象编程语言来进行类比

面向对象编程是一种编程范式或者编程风格,以类或者对象为基本单元,并且将封装 继承 多态 四个特性,作为代码设计的基石

面向对象编程语言,则是在其基础上,支持了类和对象,并且提供了语法机制来实现

那么面向过程可以说是

面向过程编程也是一种编程范式或者编程风格,以过程作为组织代码的基本单元,以数据和方法相分离为特点,通过拼接一组顺序执行的代码来完成一项功能

面向过程编程语言是一种语言,不支持类或对象的概念,不支持面向对象的编程特性

常见的对比有

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) {

// 将结构体struct User格式化成文本(”小王\t28\t男”)

}

void sort_users_by_age(struct User users[]) {

// 按照年龄从小到大排序users

}

void format_user_file(char* origin_file_path, char* new_file_path) {

// open files…

struct User users[1024]; // 假设最大1024个用户

int count = 0;

while(1) { // read until the file is empty

struct User user = parse_to_user(line);

users[count++] = user;

}

sort_users_by_age(users);

for (int i = 0; i < count; ++i) {

char* formatted_user_text = format_to_text(users[i]);

// write to new file…

}

// close files…

}

int main(char** args, int argv) {

format_user_file(“/home/zheng/user.txt”, “/home/zheng/formatted_users.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 praseFrom(String userInfoText) {

// 将text(“小王&28&男”)解析成类User

}

public String formatToText() {

// 将类User格式化成文本(”小王\t28\t男”)

}

}

public class UserFileFormatter {

public void format(String userFile, String formattedUserFile) {

// Open files…

List users = new ArrayList<>();

while (1) { // read until file is empty

// read from file into userText…

User user = User.parseFrom(userText);

users.add(user);

}

// sort users by age…

for (int i = 0; i < users.size(); ++i) {

String formattedUserText = user.formatToText();

// write to new file…

}

// close files…

}

}

public class MainApplication {

public static void main(Sring[] args) {

UserFileFormatter userFileFormatter = new UserFileFormatter();

userFileFormatter.format(“/home/zheng/users.txt”, “/home/zheng/formatted_users.txt”);

}

}

可以看出C和Java写出的区别,C中方法和数据定义是分开,Java中则是整合到了一起

2.面向对象编程和面向过程编程相比有什么优势

(1)面向对象的特性OOP,更能面对大规模复杂程序的开发

对于简单的,处理起来只有一条主线的业务来说,面向过程这种编程方式更加合适,但是对于网状的,复杂的,就不应该使用面向过程编程风格了

面向对象是以类为思考对象的,如何去聚合一个类,类和类的交互,是需要长期的思考的

而且更加合适去模块化划分某些功能,虽然C中也可以按照功能的不同,将函数和数据结构来划分到不同的文件中,但是,付出的代价比面向对象编程要多付出一些

(2)OOP的代码更容易维护

对于更加复杂的模块,一旦可以使用封装继承多态抽象这四个特性,就能体现到了面向对象编程的优势了

一旦一个类使用了封装来保护自己的可用性,那么在修改前后,都能加方便

而且,抽象这种面向过程不具有的特性,也占了非常大的一点,可以让我们在不改变原有实现的情况下,替换为新代码

继承则是面向过程编程所没有的特性之一,这个更不必说

多态,可以让我们需要重写的时候,利用接口替换,或者利用子类来替换父类,从而升级代码

所以说,这四大特性,让我们更加轻松的书写出好的代码

(3)OOP更加容易阅读

面向对象编程更加容易阅读

一开始的面向过程语言,是一条线的,更加适合机器去理解,而现在的面向对象编程,更加适合于人类去理解编码

这也是大势所趋

4.什么样的代码看起来是面向对象,实际是面向过程的

虽然我们使用的是面向对象编程语言,但是实际上经常写出的是面向过程风格的代码,那么具体怎么区分是面向对象风格,什么是面向过程风格的呢?

(1)滥用 getter setter方法

在编写Java代码的时候,经常使用Idea或者Lombok插件,直接去生成getter,setter方法,虽然看起来方便,但是实际上违反了封装这个特性,将对象的编程风格退化为了面向过程编程风格

public class ShoppingCart {

private int itemsCount;

private double totalPrice;

private List<ShoppingCartItem> items = new ArrayList<>();

public int getItemsCount() {

return this.itemsCount;

}

public void setItemsCount(int itemsCount) {

this.itemsCount = itemsCount;

}

public double getTotalPrice() {

return this.totalPrice;

}

public void setTotalPrice(double totalPrice) {

this.totalPrice = totalPrice;

}

public List<ShoppingCartItem> getItems() {

return this.items;

}

public void addItem(ShoppingCartItem item) {

items.add(item);

itemsCount++;

totalPrice += item.getPrice();

}

// …省略其他方法…

}

如上,是一个简化的购物车类,其中包含了itemsCount totalPrice items

对于 itemsCount,totalPrice两个属性,定义了其的getter,setter方法,对于items属性,定义了getter和addItem方法

如果简单的像上面一样,暴露出来,那么可以随意的设置总价这个属性,导致数据容易被篡改

面向对象的封装定义为,通过访问控制权限,来隐藏了内部数据,外部只能通过类提供的有限接口来访问,修改内部数据,对于不应该暴露的setter方法,明显违反了面向对象的封装

所以不应该书写,加上了,就成为面向过程的编程风格了

而且对于items这种集合类的对象,定义一个getter也是不应该的,因为对于一个集合类,是可以直接修改其内部属性的,如果需要暴露一个getter方法,可以考虑让getter返回一个copy对象,或者是返回一个UnmodifiableList集合,让其修改的时候直接报错,但是哈,即使是上面的getter,获取集合 中的一个对象还是可以的,于是仍然存在这篡改的风险

(2)滥用全局变量和方法

对于Java开发中,全局的变量或者方法不多见,但是有的,比如:单例类对象,静态成员变量,常量,常见的全局方法有静态方法

或者说,常见的我们会将一些参数,设置为常量,放到一个Constants类中,

将一些操作静态变量或者外部数据的方法,定义为一个Utils类中,在不创建对象的情况下,直接拿来用

但是会出现一些问题,如果一个项目将所有的常量定义到一个文件中去,比如

public class Constants {

public static final String MYSQL_ADDR_KEY = “mysql_addr”;

public static final String MYSQL_DB_NAME_KEY = “db_name”;

public static final String MYSQL_USERNAME_KEY = “mysql_username”;

public static final String MYSQL_PASSWORD_KEY = “mysql_password”;

public static final String REDIS_DEFAULT_ADDR = “192.168.7.2:7234”;

public static final int REDIS_DEFAULT_MAX_TOTAL = 50;

public static final int REDIS_DEFAULT_MAX_IDLE = 50;

public static final int REDIS_DEFAULT_MIN_IDLE = 20;

public static final String REDIS_DEFAULT_KEY_PREFIX = “rt:”;

// …省略更多的常量定义…

}

会导致降低项目的可维护性,每一次修改或者新增常量就要去翻这个类,太过于麻烦,而且再往这个类里面修改时候,会涉及到代码的编译,因为所有引用的类,都需要重新编译一次,耗时过长

所以降低了复用性和可维护性,建议将不同模块的Constants拆分成不同的类,比如MySQL的常量就应该放在MySQLConstants常量类中

对于Utils,同样需要避免去滥用,只不过在定义之前,先去想一下,是否真的需要去单独定义一个Utils类,不能将其放在其他类中吗

(3)定义数据和方法分离的类

简单来说,就是讲数据定义在一个类中,方法定义在另一个类中,如果使用的是常见的MVC三层结构来做,后端开发,很可能是书写的这样的面向过程编程风格

比如说,我们会把层次分为Controller Service Repository层,在每一层,都会定义相对应的VO BO Entity,然后将实际的方法写在Controller Service Repository类中

这种模式是一种面向过程的开发风格,也被叫做基于贫血模型的开发模式

(4)为什么会写出面向过程风格的代码呢?

因为人的思维模式导致的,习惯一步步的执行某个顺序,而不是将任务分成多个小块,设计类之间的交互,最后进行组织,

而且,面向对象编程会更加需要技巧,更加难一些,所以很容易就将代码设计为了面向过程风格的了

(5)面向过程编程就没有前途了吗

当然并非如此,如果是微小的程序,或者是单纯的数据处理的代码,那么可以使用面向过程编程

总结

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

实际上,面向过程编程和面向过程编程语言,是数据和方法相分离,相比较于面向对象编程语言,不支持封装继承多态抽象等编程特性

2.面向对象编程和面向过程编程的优势是什么

拥有类和对象的特性,更加适合去大规模复杂程序的开发

写出来的代码更加容易维护,复用

面向对象的代码更容易阅读

3.常见的面向过程的代码特性

滥用getter setter方法

Constants Uitls类的设计

贫血模型的开发设计

发表评论

邮箱地址不会被公开。 必填项已用*标注