Java之路:面向物件與面向過程
一、結構化程式設計
早期的程式設計,大量使用共享變數(全域性變數)和goto語句,這使得程式碼結構比較混亂,不容易改錯和複用。
後來有人證明所有的有意義的程式流程都可以使用順序、選擇和迴圈來實現,並由此提出結構化程式設計。
它的主要觀點是採用自頂向下、逐步求精及模組化的程式設計方法,使用三種基本控制結構構造程式,任何程式都可由順序、選擇、迴圈這三種基本控制結構來構造。
結構化程式設計主要強調的是程式的易讀性。在該程式設計思想的指導下,程式設計基本是通過寫不同目的的函式/過程來實現,故又稱為面向過程程式設計(Procedure Oriented Programming,POP))。
面向過程開發方式是對計算機底層結構的一層抽象,它把程式的內容分為資料和操縱資料的操縱兩個部分。這種程式設計方式的核心問題是資料結構和演算法的開發和優化。
結構化程式設計方法可以用一句話概括:
程式 = 演算法 + 資料結構
這裡的“演算法”可以用順序、選擇、迴圈這三種基本控制結構來實現。
這裡的“資料結構”是指資料以及其相應的存取方式。
演算法和資料結構的關係如下圖:
二、面向物件程式設計
(Object-oriented programming,OOP)
面向物件的思想主要是基於抽象資料型別(Abstract Data Type, ADT)。
在結構化程式設計過程中,人們發現把某種資料結構和專用於操縱它的各種操作以某種模組化方式繫結到一起會非常方便,做到“特定資料對應特定處理方法
抽象資料型別方法雖然也有一定的抽象能力,但其核心仍然是資料結構和演算法。
而面向物件方法直接把所有事物都當作獨立的物件,處理問題過程中所思考的不再主要是怎樣用資料結構來描述問題,而是直接考慮重現問題中各個物件之間的關係。可以說,面向物件革命的最重要價值就在於改變了人們看待和處理問題的方式。
例如,在現實世界中桌子代表了所有具有桌子特徵的事物,人類代表了所有具有人特徵的生物。
這個事物的類別對映到計算機程式中,就是面向物件中類(class)的概念。
可以將現實世界中的任何實體都看作是物件。
例如在人類中有個叫張三的人,張三就是人類中的實體。
物件之間通過訊息相互作用。
比如張三這個物件和李四這個物件通過說話的方式相互傳遞訊息。
現實世界中的物件均有屬性和行為。
例如張三有屬性:手、腳、臉等,行為有:說話、走路、吃飯等。
類似的,對映到計算機程式上,屬性則表示物件的資料,行為表示物件的方法(其作用是處理資料或同外界互動)。
現實世界中的任何實體都可歸屬於某類事物,任何物件都是某一類事物的例項。
所以在面向物件的程式設計中一個類可以例項化多個相同型別的物件。
面向物件程式設計達到了軟體工程的三個主要目標:重用性、靈活性和擴充套件性。
三、面向物件程式設計的基本特徵
主要特徵:封裝性、繼承性、多型性。
1、封裝性(encapsulation)
封裝是一種資訊隱蔽技術,它體現於類的說明,是物件的重要特性。
封裝使資料和加工該資料的方法(函式)封裝為一個整體,以實現獨立性很強的模組,使得使用者只能見到物件的外特性(物件能接受哪些訊息,具有哪些處理能力),而物件的內特性(儲存內部狀態的私有資料和實現加工能力的演算法)對使用者是隱蔽的。
封裝的目的在於把物件的設計者和物件的使用者分開,使用者不必知曉其行為實現的細節,只須用設計者提供的訊息來訪問該物件。
2、繼承性
繼承性是子類共享其父類資料和方法的機制。它由類的派生功能體現。
一個類直接繼承其他類的全部描述,同時可修改和擴充。
繼承具有傳遞性。
繼承分為單繼承(一個子類有一父類)和多重繼承(一個類有多個父類)。
類的物件是各自封閉的,如果沒繼承性機制,則類的物件中的資料、方法就會出現大量重複。
繼承不僅支援系統的可重用性,而且還促進系統的可擴充性。
3、多型性
物件根據所接收的訊息而做出動作。
同一訊息被不同的物件接受時可產生完全不同的行動,這種現象稱為多型性。
利用多型性使用者可傳送一個通用的資訊,而將所有的實現細節都留給接受訊息的物件自行決定,如是,同一訊息即可呼叫不同的方法。
例如:同樣是run方法,飛鳥呼叫時是飛,野獸呼叫時是奔跑。
多型性的實現受到繼承性的支援,利用類繼承的層次關係,把具有通用功能的協議存放在類層次中儘可能高的地方,而將實現這一功能的不同方法置於較低層次,這樣,在這些低層次上生成的物件就能給通用訊息以不同的響應。
在OOPL中可通過在派生類中重定義基類函式(定義為過載函式或虛擬函式)來實現多型性。
綜上可知,在面對象方法中,物件和傳遞訊息分別表現事物及事物間相互聯絡的概念。
類和繼承是適應人們一般思維方式的描述正規化。方法是允許作用於該類物件上的各種操作。
這種物件、類、訊息和方法的程式設計正規化的基本點在於物件的封裝性和類的繼承性。
通過封裝能將物件的定義和物件的實現分開,通過繼承能體現類與類之間的關係,以及由此實現動態聯編和實體的多型性,從而構成了面向物件的基本特徵。
四、面向物件程式設計和麵向過程程式設計的比較
1、兩種程式設計正規化之間的區別
- 面向過程
面向過程程式設計採用的是“自上而下,步步求精”的程式設計思想,人們更易於理解這種思想。
將程式一步一步的分解,並按照一定的順序執行。這就是面向過程程式設計,以過程為中心,以演算法為驅動。
程式 = 演算法 + 資料結構
缺點:面向過程的程式上一步和下一步環環相扣,如果需求發生變化那麼程式碼的改動會很大,這樣很不利於軟體的後期維護和擴充套件。
- 面向物件
面向物件程式設計的出現就可以很好的解決了這一問題,它的設計思想是:
程式 = 物件 + 訊息傳遞
使用者首先自定義的資料結構——“類”,然後用該型別下的“物件” 組裝程式。物件之間通過“訊息”進行通訊。每個物件包括資料以及對資料的處理,每個物件都像是一個小型的“機器” 。
優點:面向物件設計使程式更容易擴充套件,也更加符合現實世界的模型。
缺點:但是 “任何事物都有兩面性”,面向物件程式設計有其優點,但也帶來了“副作用”——執行效率要低於面向過程程式設計。
所以進行科學計算和要求高效率的程式中,面向過程設計要好於面向物件設計。而且面向物件程式的複雜度要高於面向過程的程式,如果程式比較小,面向過程要比面向物件更加清晰。
更為具體來說,為解決某個任務,面向過程程式設計首先強調的“該怎麼做(How to do?)” 。
這裡的“How對應的解決方案就形成一個個功能塊—function(函式)。
而面向物件程式設計首先考慮的是 “該讓誰來做(Who to do?)”。
這裡的Who就是物件,這些物件完成某項任務的能力就構成一個個method(方法),最後一系列具備一定的方法的物件“合力”能把任務完成。
例如,對於“吃東西”這個任務,面向過程強調的是“如何去吃”,“人”只是一個引數;而面向物件強調的是“人”,“吃東西”只是人內部能實現的一個方法。二者之間的對比如下圖所示。
2、兩種程式設計正規化之間的聯絡
面向物件是在面向過程的基礎上發展而來的,只是新增了它獨有的一些特性。
面向物件程式中的物件就是由資料和方法構成,所以完整的面向物件概念應該是:
物件 = 資料 + 方法
更進一步的可以描述為:
程式 =物件 + 訊息傳遞 = (資料 + 方法) +訊息傳遞