1. 程式人生 > >面向物件程式設計與面向過程程式設計解析

面向物件程式設計與面向過程程式設計解析

昨天晚上在知乎看到這個問題,一時還真說不太清。之前一直用JAVA和Android做開發,最近在維護一個老的專案,是用VB開發的,程式碼超過十個年頭了,接觸了一段時間。對面向過程和麵向物件都有所涉及,在這裡這個小結(有些是在網上收集的)

自己的理解:
面向過程是一種以事件為中心的程式設計思想,以功能(行為)為導向,按模組化的設計,就是分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步實現,實現的時候一個一個依次呼叫就可以了
面向物件是一種以事物為中心的程式設計思想,以資料(屬性)為導向,將具有相同一個或者多個屬性的物體抽象為“類”,將他們包裝起來;而有了這些資料(屬性)之後,我們再考慮他們的行為(對這些屬性進行怎樣的操作),是把構成問題的事物分解成各個物件,建立物件的目的不是為了完成一個步驟,而是為了描述某個事物在整個解決問題的步驟中的行為。面嚮物件的技術,是一種以物件為基礎,以事件或訊息來驅動物件執行處理的程式設計技術。它具有封裝性,繼承性以及多型性。

知乎網友rlei;

面向物件程式設計強調“封裝”,“繼承“和“多型”。資料和與資料相關的操作被包裝成物件(嚴格的說是“類”),每一種物件是相對完整和獨立的。物件可以有派生的型別,派生的型別可以覆蓋(或過載)原本已有的操作。所有的這些,是為了達成更好的內聚性,即一種物件做好一件(或者一類相關的)事情,物件內部的細節外面世界不關心也看不到;以及降低耦合性,即不同種類的物件之間相互的依賴儘可能降低。而所有的這些,都有助於達成一個崇高的目標,就是可複用性。別人寫出來的東西,你可以簡簡單單拿過來用,還可以加以發展,這不是一個很美好的世界嗎?

精講

面向過程就是分析出解決問題所需要的步驟,然後用函式把這些步驟一步一步實現,使用的時候一個一個依次呼叫就可以了。面向物件是把構成問題事務分解成各個物件,建立物件的目的不是為了完成一個步驟,而是為了描敘某個事物在整個解決問題的步驟中的行為。

面向過程

面向過程的程式設計是一種自上而下的設計方法,設計者用一個main函式概括出整個應用程式需要做的事,而main函式由對一系列子函式的呼叫組成。對於main中的每一個子函式,都又可以再被精煉成更小的函式。重複這個過程,就可以完成一個過程式的設計。其特徵是以函式為中心,用函式來作為劃分程式的基本單位,資料在過程式設計中往往處於從屬的位置。

  面向過程式設計的優點是易於理解和掌握,這種逐步細化問題的設計方法和大多數人的思維方式比較接近。

  然而,過程式設計對於比較複雜的問題,或是在開發中需求變化比較多的時候,往往顯得力不從心。這是因為過程式的設計是自上而下的,這要求設計者在一開始就要對需要解決的問題有一定的瞭解。在問題比較複雜的時候,要做到這一點會比較困難,而當開發中需求變化的時候,以前對問題的理解也許會變得不再適用。事實上,開發一個系統的過程往往也是一個對系統不斷了解和學習的過程,而過程式的設計方法忽略了這一點。



  在面向過程式設計的語言中,一般都既有定義資料的元素,如C語言中的結構,也有定義操作的元素,如C語言中的函式。這樣做的結果是資料和操作被分離開,容易導致對一種資料的操作分佈在整個程式的各個角落,而一個操作也可能會用到很多種資料,在這種情況下,對資料和操作的任何一部分進行修改都會變得很困難。

  在面向過程式設計中,main()函式處於一個非常重要的地位。設計者正是在main()函式中,對整個系統進行一個概括的描述,再以此為起點,逐步細化出整個應用程式。然而,這樣做的一個後果,是容易將一些較外延和易變化的邏輯(比如使用者互動)同程式的核心邏輯混淆在一起。假設我們編寫一個圖形介面的計算器程式和一個命令列介面的計算器程式,可以想象這兩個版本的main()函式會有很大的差異,由此衍生出來的程式很有可能也會迥然不同,而這兩個版本的程式本應該有很大部分可以共用才對。

  面向過程式設計還有一個問題就是其程式架構的依賴關係問題。一個典型的過程式程式往往如Figure 1所示:

 
  Figure 1


  圖中的箭頭代表了函式間的呼叫關係,也是函式間的依賴關係。如圖所示,main()函式依賴於其子函式,這些子函式又依賴於更小的子函式,而在程式中,越小的函式處理的往往是細節實現,這些具體的實現,又常常變化。這樣的結果,就是程式的核心邏輯依賴於外延的細節,程式中本來應該是比較穩定的核心邏輯,也因為依賴於易變化的部分,而變得不穩定起來,一個細節上的小小改動,也有可能在依賴關係上引發一系列變動。可以說這種依賴關係也是過程式設計不能很好處理變化的原因之一,而一個合理的依賴關係,應該是倒過來,由細節實現依賴於核心邏輯才對。

面向物件設計

  面向物件是一種自下而上的程式設計方法。不像過程式設計那樣一開始就要用main概括出整個程式,面向物件設計往往從問題的一部分著手,一點一點地構建出整個程式。面向物件設計以資料為中心,類作為表現資料的工具,是劃分程式的基本單位。而函式在面向物件設計中成為了類的介面。

  面向物件設計自下而上的特性,允許開發者從問題的區域性開始,在開發過程中逐步加深對系統的理解。這些新的理解以及開發中遇到的需求變化,都會再作用到系統開發本身,形成一種螺旋式的開發方式。(在這種開發方式中,對於已有的程式碼,常需要運用Refactoring技術來做程式碼重構以體現系統的變化。)

  和函式相比,資料應該是程式中更穩定的部分,比如,一個網上購物程式,無論怎麼變化,大概都會處理貨物、客戶這些資料物件。不過在這裡,只有從抽象的角度來看,資料才是穩定的,如果考慮這些資料物件的具體實現,它們甚至比函式還要不穩定,因為在一個數據物件中增減欄位在程式開發中是常事。因此,在以資料為中心構建程式的同時,我們需要一種手段來抽象地描述資料,這種手段就是使用函式。在面向物件設計中,類封裝了資料,而類的成員函式作為其對外的介面,抽象地描述了類。用類將資料和操作這些資料的函式放在一起,這可以說就是面向物件設計方法的本質。

  在面向物件設計中類之間的關係有兩種:客戶(Client)關係和繼承(Inheritance)關係。客戶關係如Figure 2所示,表示一個類(Client)會使用到另一個類(Server)。一般將這種關係中的Client類稱為客戶端,Server類稱為伺服器
 
  Figure 2


  繼承關係如Figure 3所示,表示一個類(Child)對另一個類(Parent)的繼承。一般將這種關係中的Parent類稱為父類,Child類稱為子類。
 
  Figure 3


  面向物件設計的過程就是將各個類按以上的兩種關係組合在一起,這兩種關係都非常簡單,不過組合在一起卻能提供強大的設計能力。下面介紹如何利用這兩種關係來劃分程式的不同模組。

  在很多應用中,我們都需要將資料儲存到資料庫中。一個常見的解決手段是使用分層的方法,將程式分為應用層和儲存層,Figure 4中是這種方法一個不太成熟的設計:
 
  Figure 4


  Application代表應用層的邏輯,DB代表了資料庫訪問的邏輯,在這個設計中,Application直接呼叫了DB的服務來將資料儲存到資料庫中。這樣做的缺點是Application對DB有了依賴關係,一旦DB有了任何變化,Application都有可能會受其影響需要改動。當然,如果只是兩個類的話,這種依賴關係根本算不上什麼問題,然而,我們有理由相信,應用層和儲存層都會由不只一個類組成,並都有一定的複雜度,這時它們之間的這種依賴關係就會讓人頭痛了。當程式的模組越來越多,如果不限制它們之間的聯絡,那模組間的依賴、程式的複雜度和開發維護的難度都會成指數上升。

  所幸的是引入面向物件中的繼承關係,我們可以解決這一問題,如圖Figure 5所示:
 
  Figure 5


  Persistence是一個介面,其包含了Application儲存所需用到的服務。DB實現了這個介面,Application則呼叫Persistence中的服務來儲存資料,兩者都只依賴於Persistence。這樣,Application到DB的依賴關係被Persistence這個介面切斷了。因為介面中只包含了服務,也就是成員函式的宣告,而不包括任何資料和函式的實現,所以Persistence介面的內容會很簡單。在Persistence不變的情況下,Application和DB這兩個模組都可以自由地進行修改而不影響到對方。就這樣,通過在中間插入介面的方法,程式的模組被劃分開,依賴關係也變得容易管理的多。

  如果從另一個角度來看Figure 4中的設計,應用層是程式的核心部分,而儲存層則可以看成是實現的細節,這個設計犯了和過程式設計同樣的錯誤,即核心邏輯依賴於具體的實現細節,這樣,當細節變化時,核心邏輯也會受到影響:假如,當我們需要將資料改存到檔案或目錄服務中時,按照Figure 4中的設計Application模組就難免受到影響。在Figure 5的設計中則沒有這一問題:這裡我們可以把Application和Persistence看成是程式的核心邏輯,而Persistence介面的實現(DB)可以看成是程式的細節實現,其依賴關係是細節依賴於核心,當細節變化時核心不會受其影響,這才是一個穩定的依賴關係。遵從這一設計,我們可以在不影響程式核心的情況下,為程式新增或更改儲存型別,如Figure 6所示:
 
  Figure 6


  這裡值得注意的是Persistence和Application被劃分到了一起,這是因為Persistence中的服務都是根據Application中的需求制定出來的,Persistence和Application的關係比起它和其子類的關係更加緊密。將介面和其呼叫者放入一個模組是一個常見的做法,當然,也可以將介面單獨劃分為一個模組,這一般是在有多個不同的呼叫模組依賴於該介面,或不同模組間需要更清晰的分離時才這樣做。

相關推薦

面向物件開發面向物件設計模式的幾個核心的思想和概念 -java

  面向物件方法,OO方法所具有的模組化、資訊封裝與隱蔽、抽象性、繼承性、多樣性等獨特之處,這些優異特性為研製大型軟體、提高軟體可靠性、可重用性、可擴充性和可維護性提供了有效的手段和途徑。Java主要特徵:封裝性,繼承性,多型性. >>>> 面向物件

面向物件程式設計面向過程程式設計解析

昨天晚上在知乎看到這個問題,一時還真說不太清。之前一直用JAVA和Android做開發,最近在維護一個老的專案,是用VB開發的,程式碼超過十個年頭了,接觸了一段時間。對面向過程和麵向物件都有所涉及,在這裡這個小結(有些是在網上收集的) 自己的理解: 面向過程是一種以事件為中

面向過程程式設計面向物件程式設計

1.面向過程程式設計   核心是過程二字,過程指的就是解決問題的不走,即先幹什麼再幹什麼後幹什麼...   基於該思想編寫程式就好比在設計一條流水線,是一種機械師的思維方式   優點:複雜的問題流程化,進而簡單化   缺點:可擴充套件性差 2.面向物件程式設計   核心是物件二字,物件是特徵與技能

面向物件程式設計面向過程程式設計的特點

一、面向過程程式設計 1)傳統的結構化程式設計通過設計一系列的過程(即演算法)來解決問題。當確定過程之後,再開始考慮儲存資料的方式。演算法是第一位的,資料結構是第二位的。 2)首先確定如何操作資料,然後再決定如何組織資料,以便於資料操作。 3)面向過程是一種以事件為中

函數語言程式設計面向物件程式設計的比較

            函數語言程式設計作為結構化程式設計的一種,正在受到越來越多的重視。工程中不在只是面向物件程式設計,更多的人嘗試著開始使用函數語言程式設計來解決軟體工程中遇到的問題。             什麼是函數語言程式設計?在維基百科中給出了詳細的定義,函

JavaScript面向物件程式設計和麵向過程程式設計

JavaScript程式設計中多數情況是面向過程程式設計,但有時候為了更好地封裝重用。面向物件思想來程式設計更為有用。 雖然現前端都開始流行MVC思想的js框架,但並不是說js沒用了,學好js對於學習js前端框架,jquery,等都是非常有幫助的。 好了,閒話不說,下面用一

畫板(面向物件設計,外掛式程式設計

畫板 設計上的主要特點 多型: 使用虛擬函式,讓呼叫者不加區分地完成函式呼叫. 該特點體現在畫板主程式對Painter類方法的呼叫上,以此實現對多種圖形的操作. 繼承: 每次實現一個新的畫圖選項(比如畫矩形)都需要子類化4個基類Shape,Pain

面向對象面向過程編程

算法 面向過程編程 代碼 底層 面向 高效率 是把 一個 才會 兩種思想的對比: 面向過程是具體的東西,而且面向過程是面向對象的基礎。面向對象可以說是面向過程的抽象,比如汽車有開車,加減速和剎車,關於汽車的操作有好多,每一個都需要一個具體的過程來實現,把這些過程抽象的總結起

面向對象-面向對象面向過程優缺點

復雜度 用途 完成 互聯 應用 辦公系統 步驟 聯網 題解 面向過程: 面向過程編程,核心是過程,即解決問題的步驟,設計一條解決問題的流水線。把大問題分揀成小問題解決,之後再串接起來。 優點:復雜問題流程話,簡化問題,降低復雜度 缺點:可擴展性插,牽一發而動全身 用途:工

面向物件類之間的關係 (依賴,組合,聚合,等)

-----------------------------困難是一位嚴厲的老師,他產生於克服困難的努力中。 # ---------------------------------------------------------------------------------# # class Page:#

面向物件objectconstructor

什麼是constructor屬性?它來自哪裡?又將會指向何處? 什麼是constructor屬性? constructor是建構函式屬性。 它來自哪裡? 其實constructor屬性是來自 prototy原型屬性 所指向的那個物件的屬性,如果不明白這裡的“那個物件”具體指

JS中objectconstructor的分析 面向物件objectconstructor

  面向物件object與constructor    (本文轉自:http://www.cnblogs.com/chengxiangboke/p/9932790.html) 什麼是constructor屬性?它來自哪裡?又將會指向何處?

Java面向物件——類方法

面向物件——能進行現實生活的抽象 世界是由一系列物件互相組合形成(多個物件之間的相互協作),每個物件有自己的屬性和方法。 通俗解釋:狗吃糧,狗和糧是兩個物件 ,吃是行為 每個物件——類,每個類有自己的屬性及方法 新興的程式設計正規化: 面向切面程式設計:EE-AOP 面向介面

Java 面向物件-類物件

Java面向物件-類與物件   類與物件的關係 我們通俗的舉個例子,比如人類是一種類,張三這個人就是人類的具體的一個個體,也就是java中的物件;這就是一個類與物件的關係;   類的定義 下面看例項   類的建立和使用 package com.xuyiga

JAVA中OOAD(面向物件分析設計依賴倒置原則)程式碼例項

簡介:什麼是依賴倒置原則? 軟體設計中,多層次之間相互依賴關係需要倒置為抽象類或介面,而不是直接依賴於具體的實現。 具體表現為: 1、上層模組不應該直接依賴下層實現,而應該依賴下層的抽象 2、每一個單獨的層次,抽象不應該依賴於細節,而細節應該依賴於抽象。 現在有一個使用者類UserBea

面向物件objectconstructor 面向物件objectconstructor

面向物件object與constructor   什麼是constructor屬性?它來自哪裡?又將會指向何處? 什麼是constructor屬性? constructor是建構函式屬性。 它來自哪裡?

031_面向物件_04_程式執行過程的記憶體分析_01

一、概念部分   a)屬性(field):也叫成員變數,在類體(類內方法外)的變數部分中定義的變數。     屬性用於定義該類或該類物件包含的資料或者說靜態屬性。屬性的作用範圍是整個類體   b)區域性變數:定義在語句塊/方法裡面的變數。只有該語句塊、方法能使用,並且使用前必須要進行手動初始化。語句塊或

032_面向物件_05_程式執行過程的記憶體分析_02

一、例項程式碼   package edu.aeon.test; /** * [說明]計算機類 * @author aeon */ public class Computer { /**計算機品牌*/ public String brand; /**計算機cpu速度*/

Java面向物件——類方法(練習:將車抽象為類)

程式碼: public class Car{ //屬性 //品牌(不可更改)、產地(不可更改)、顏色、價格 private String brand; private String origin; private String colour; private int price;

day25-面向物件結構成員

1、面向物件結構分析 如下面的圖所示:面向物件整體大致分兩塊區域:   每個大區域又可以分為多個小部分: class A: name = 'Tom' # 靜態變數(靜態欄位) __iphone = '138xxxxxxxx' # 私有靜態變數(私有靜態欄位)