設計模式之美學習(四):面向對象相比面向過程有哪些優點?面向過程真的過期了嗎?

除了面向對象以外,被你們熟知的編程範式還有另外兩種,面向過程編程和函數式編程。面向過程這種編程範式隨着面向對象的出現,已經慢慢退出了舞臺,而函數式編程目前尚未被普遍接受。java

在工做中,不少人搞不清楚面向對象和麪向過程的區別,總覺得使用面向對象編程語言來作開發,就是在進行面向對象編程了。而實際上,他們只是在用面向對象編程語言,編寫面向過程風格的代碼而已,並無發揮面向對象編程的優點。這就至關於手握一把屠龍刀,卻只是把它看成一把普通的刀劍來用,至關惋惜。編程

什麼是面向過程編程與面向過程編程語言?

咱們能夠對比着面向對象編程和麪向對象編程語言這兩個概念,來理解面向過程編程和麪向過程編程語言。還記得以前是如何定義面向對象編程和麪向對象編程語言的嗎?讓咱們一塊再來回顧一下。小程序

  • 面向對象編程是一種編程範式或編程風格。它以類或對象做爲組織代碼的基本單元,並將封裝、抽象、繼承、多態四個特性,做爲代碼設計和實現的基石 。數據結構

  • 面向對象編程語言是支持類或對象的語法機制,並有現成的語法機制,能方便地實現面向對象編程四大特性(封裝、抽象、繼承、多態)的編程語言。編程語言

類比面向對象編程與面向對象編程語言的定義,對於面向過程編程和麪向過程編程語言這兩個概念,給出下面這樣的定義。模塊化

  • 面向過程編程也是一種編程範式或編程風格。它以過程(能夠爲理解方法、函數、操做)做爲組織代碼的基本單元,以數據(能夠理解爲成員變量、屬性)與方法相分離爲最主要的特色。面向過程風格是一種流程化的編程風格,經過拼接一組順序執行的方法來操做數據完成一項功能。函數式編程

  • 面向過程編程語言首先是一種編程語言。它最大的特色是不支持類和對象兩個語法概念,不支持豐富的面向對象編程特性(好比繼承、多態、封裝),僅支持面向過程編程。函數

不過,這裏必須聲明一下,就像咱們在以前講到的,面向對象編程和麪向對象編程語言並無官方的定義同樣,這裏我給出的面向過程編程和麪向過程編程語言的定義,也並非嚴格的官方定義。之因此要給出這樣的定義,只是爲了跟面向對象編程及面向對象編程語言作個對比,以方便你理解它們的區別。this

定義不是很嚴格,也比較抽象,因此,我再用一個例子進一步解釋一下。假設咱們有一個記錄了用戶信息的文本文件 users.txt,每行文本的格式是 name&age&gender(好比,小王 &28& 男)。咱們但願寫一個程序,從 users.txt 文件中逐行讀取用戶信息,而後格式化成 name\tage\tgender(其中,\t 是分隔符)這種文本格式,而且按照 age 從小到達排序以後,從新寫入到另外一個文本文件 formatted_users.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) {
  // 將結構體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");
}

而後,咱們再來看,用面向對象這種編程風格寫出來的代碼是什麼樣子的。注意,下面的代碼是用 Java 這種面向對象的編程語言來編寫的。

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&男」)解析成結構體struct User
  }
  
  public String formatToText() {
    // 將結構體struct 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");
  }
}

從上面的代碼中,咱們能夠看出,面向過程和麪向對象最基本的區別就是,代碼的組織方式不一樣。面向過程風格的代碼被組織成了一組方法集合及其數據結構(struct User),方法和數據結構的定義是分開的。面向對象風格的代碼被組織成一組類,方法和數據結構被綁定一塊兒,定義在類中。

面向對象編程相比面向過程編程有哪些優點?

爲何面向對象編程晚於面向過程編程出現,卻能取而代之,成爲如今主流的編程範式?面向對象編程跟面向過程編程比起來,到底有哪些優點?

1.OOP 更加可以應對大規模複雜程序的開發

對於簡單程序的開發來講,不論是用面向過程編程風格,仍是用面向對象編程風格,差異確實不會很大,甚至有的時候,面向過程的編程風格反倒更有優點。由於需求足夠簡單,整個程序的處理流程只有一條主線,很容易被劃分紅順序執行的幾個步驟,而後逐句翻譯成代碼,這就很是適合採用面向過程這種麪條式的編程風格來實現。

但對於大規模複雜程序的開發來講,整個程序的處理流程錯綜複雜,並不是只有一條主線。若是把整個程序的處理流程畫出來的話,會是一個網狀結構。若是咱們再用面向過程編程這種流程化、線性的思惟方式,去翻譯這個網狀結構,去思考如何把程序拆解爲一組順序執行的方法,就會比較吃力。這個時候,面向對象的編程風格的優點就比較明顯了。

面向對象編程是以類爲思考對象。在進行面向對象編程的時候,咱們並非一上來就去思考,如何將複雜的流程拆解爲一個一個方法,而是採用曲線救國的策略,先去思考如何給業務建模,如何將需求翻譯爲類,如何給類之間創建交互關係,而完成這些工做徹底不須要考慮錯綜複雜的處理流程。當咱們有了類的設計以後,而後再像搭積木同樣,按照處理流程,將類組裝起來造成整個程序。這種開發模式、思考問題的方式,能讓咱們在應對複雜程序開發的時候,思路更加清晰。

除此以外,面向對象編程還提供了一種更加清晰的、更加模塊化的代碼組織方式。好比,咱們開發一個電商交易系統,業務邏輯複雜,代碼量很大,可能要定義數百個函數、數百個數據結構,那如何分門別類地組織這些函數和數據結構,才能不至於看起來比較凌亂呢?類就是一種很是好的組織這些函數和數據結構的方式,是一種將代碼模塊化的有效手段。

實際上,利用面向過程的編程語言照樣能夠寫出面向對象風格的代碼,只不過可能會比用面向對象編程語言來寫面向對象風格的代碼,付出的代價要高一些。並且,面向過程編程和麪向對象編程並不是徹底對立的。不少軟件開發中,儘管利用的是面向過程的編程語言,也都有借鑑面向對象編程的一些優勢。

2.OOP 風格的代碼更易複用、易擴展、易維護

面向過程編程是一種很是簡單的編程風格,並無像面向對象編程那樣提供豐富的特性。而面向對象編程提供的封裝、抽象、繼承、多態這些特性,能極大地知足複雜的編程需求,能方便咱們寫出更易複用、易擴展、易維護的代碼。爲何這麼說呢?

首先,咱們先來看下封裝特性。封裝特性是面向對象編程相比於面向過程編程的一個最基本的區別,由於它基於的是面向對象編程中最基本的類的概念。面向對象編程經過類這種組織代碼的方式,將數據和方法綁定在一塊兒,經過訪問權限控制,只容許外部調用者經過類暴露的有限方法訪問數據,而不會像面向過程編程那樣,數據能夠被任意方法隨意修改。所以,面向對象編程提供的封裝特性更有利於提升代碼的易維護性。

其次,咱們再來看下抽象特性。咱們知道,函數自己就是一種抽象,它隱藏了具體的實現。咱們在使用函數的時候,只須要了解函數具備什麼功能,而不須要了解它是怎麼實現的。從這一點上,無論面向過程編程仍是是面向對象編程,都支持抽象特性。不過,面向對象編程還提供了其餘抽象特性的實現方式。這些實現方式是面向過程編程所不具有的,好比基於接口實現的抽象。基於接口的抽象,可讓咱們在不改變原有實現的狀況下,輕鬆替換新的實現邏輯,提升了代碼的可擴展性。

再次,咱們來看下繼承特性。繼承特性是面向對象編程相比於面向過程編程所特有的兩個特性之一(另外一個是多態)。若是兩個類有一些相同的屬性和方法,咱們就能夠將這些相同的代碼,抽取到父類中,讓兩個子類繼承父類。這樣兩個子類也就能夠重用父類中的代碼,避免了代碼重複寫多遍,提升了代碼的複用性。

最後,咱們來看下多態特性。基於這個特性,咱們在須要修改一個功能實現的時候,能夠經過實現一個新的子類的方式,在子類中重寫原來的功能邏輯,用子類替換父類。在實際的代碼運行過程當中,調用子類新的功能邏輯,而不是在原有代碼上作修改。這就聽從了「對修改關閉、對擴展開放」的設計原則,提升代碼的擴展性。除此以外,利用多態特性,不一樣的類對象能夠傳遞給相同的方法,執行不一樣的代碼邏輯,提升了代碼的複用性。

因此說,基於這四大特性,利用面向對象編程,咱們能夠更輕鬆地寫出易複用、易擴展、易維護的代碼。固然,咱們不能說,利用面向過程風格就不能夠寫出易複用、易擴展、易維護的代碼,但沒有四大特性的幫助,付出的代價可能就要高一些。

3.OOP 語言更加人性化、更加高級、更加智能

人類最開始跟機器打交道是經過 01 這樣的二進制指令,而後是彙編語言,再以後纔出現了高級編程語言。在高級編程語言中,面向過程編程語言又早於面向對象編程語言出現。之因此先出現面向過程編程語言,那是由於跟機器交互的方式,從二進制指令、彙編語言到面向過程編程語言,是一個很是天然的過渡,都是一種流程化的、麪條式的編程風格,用一組指令順序操做數據,來完成一項任務。

從指令到彙編再到面向過程編程語言,跟機器打交道的方式在不停地演進,從中咱們很容易發現這樣一條規律,那就是編程語言愈來愈人性化,讓人跟機器打交道愈來愈容易。籠統點講,就是編程語言愈來愈高級。實際上,在面向過程編程語言以後,面向對象編程語言的出現,也順應了這樣的發展規律,也就是說,面向對象編程語言比面向過程編程語言更加高級!

跟二進制指令、彙編語言、面向過程編程語言相比,面向對象編程語言的編程套路、思考問題的方式,是徹底不同的。前三者是一種計算機思惟方式,而面向對象是一種人類的思惟方式。咱們在用前面三種語言編程的時候,咱們是在思考,如何設計一組指令,告訴機器去執行這組指令,操做某些數據,幫咱們完成某個任務。而在進行面向對象編程時候,咱們是在思考,如何給業務建模,如何將真實的世界映射爲類或者對象,這讓咱們更加能聚焦到業務自己,而不是思考如何跟機器打交道。能夠這麼說,越高級的編程語言離機器越「遠」,離咱們人類越「近」,越「智能」。

順着剛剛這個編程語言的發展規律來想,若是一種新的突破性的編程語言出現,那它確定是更加「智能」的。大膽想象一下,使用這種編程語言,咱們能夠無需對計算機知識有任何瞭解,無需像如今這樣一行一行地敲不少代碼,只須要把需求文檔寫清楚,就能自動生成咱們想要的軟件了。

重點回顧

1. 什麼面向過程編程?什麼面向過程編程語言?

實際上,面向過程編程和麪向過程編程語言並無嚴格的官方定義。理解這兩個概念最好的方式是跟面向對象編程和麪向對象編程語言進行對比。相較於面向對象編程以類爲組織代碼的基本單元,面向過程編程則是以過程(或方法)做爲組織代碼的基本單元。它最主要的特色就是數據和方法相分離。相較於面向對象編程語言,面向過程編程語言最大的特色就是不支持豐富的面向對象編程特性,好比繼承、多態、封裝。

2. 面向對象編程相比面向過程編程有哪些優點?

  • 面向對象編程相比起面向過程編程的優點主要有三個。
    對於大規模複雜程序的開發,程序的處理流程並不是單一的一條主線,而是錯綜複雜的網狀結構。面向對象編程比起面向過程編程,更能應對這種複雜類型的程序開發。

  • 面向對象編程相比面向過程編程,具備更加豐富的特性(封裝、抽象、繼承、多態)。利用這些特性編寫出來的代碼,更加易擴展、易複用、易維護。

  • 從編程語言跟機器打交道的方式的演進規律中,咱們能夠總結出:面向對象編程語言比起面向過程編程語言,更加人性化、更加高級、更加智能。

思考

面向對象編程比面向過程編程,更加容易應對大規模複雜程序的開發。但像 UnixLinux 這些複雜的系統,也都是基於 C 語言這種面向過程的編程語言開發的,怎麼看待這個現象?

參考:面向對象相比面向過程有哪些優點?面向過程真的過期了嗎?

本文由博客一文多發平臺 OpenWrite 發佈!
更多內容請點擊個人博客 沐晨

相關文章
相關標籤/搜索