本章介紹如何使用設計模式來寫具有健壯性、可維護性、可延伸性的程式碼,以及Java的最新特性。爲此,我們需要討論以下問題:[插圖]
什麼是程式設計範式[插圖]
命令式範式[插圖]
宣告式和函數式範式[插圖]
物件導向範式[插圖]
統一建模語言(UML)
綜述[插圖]
物件導向原則
什麼是程式設計範式,自從有軟件開發開始,開發人員嘗試了不同的方式來設計程式語言。對於不同的程式語言,我們都有一系列的概念、原則和規定。這些概念、原則和規定就被稱爲程式設計範式。從理論上來說,我們希望程式語言只遵從一個程式設計範式。但是實際上,一個語言往往擁有多個程式設計範式。在接下來的幾節裡,我們會重點介紹Java語言所基於的程式設計範式,包括命令式、物件導向、宣告式和函數語言程式設計,以及用來描述這些程式設計範式的主要概念。
指令式程式設計是這樣一種程式設計範式:用語句更改程式的狀態。這個概念出現在運算的開始,並且與計算機的內部結構緊密相連。程式是處理單元上執行的一組指令,它以命令的方式改變狀態(狀態即記憶體中的變數)。「命令」這個名稱,顧名思義,指令的執行即是程式的執行。今天大多數流行的程式語言或多或少都基於指令式程式設計發展而來。命令式語言最典型的範例就是C語言。
指令式程式設計範例爲了更好地理解指令式程式設計範式的概念,讓我們舉一個例子:你計劃在某城鎮與一個朋友會面,但他不知道如何到達那裏。我們來試着以「命令式」的方式向他解釋如何實現目標:1)在中央火車站乘坐1號電車;2)在第三站下車;3)向右走,朝第六大道行進,直到到達第三個路口。
物件導向程式設計經常與指令式程式設計聯繫在一起,在實踐當中,兩者是可以共存的。Java就是這種共同作業的生動證明。接下來,我們將簡要介紹物件導向的基本概念,程式碼都會以Java語言實現。
讓我們回想之前提到的現實生活中的指令式程式設計例子,我們指導朋友如何到達一個地方。當我們從宣告式程式設計範式的角度思考,我們並不告訴朋友如何到達特定位置,而是簡單地給他地址並讓他弄清楚如何到達那裏。在這種情況下,我們並不關心他是否使用地圖或GPS,或者他是否向別人求助,而是告訴他該做什麼:上午9:30到達第五大道和第九大道之間的交界處。與指令式程式設計相反,宣告式程式設計是這樣一種程式設計範式:它指定程式應該做什麼,而不具體說明怎麼做。純粹的宣告式語言套件括數據庫查詢語言(如SQL和XPath)以及正則表達式。與指令式程式設計語言相比,宣告式程式語言更抽象。它們並不模擬硬體結構,因此不會改變程式的狀態,而是將它們轉換爲新狀態,並且更接近數學邏輯。通常,非命令式的程式設計範式都被認爲屬於宣告式類別。這就是爲什麼有許多型別的範式屬於宣告式類別。在我們的探索中,我們會看到與本書內容唯一相關的一個宣告式程式設計範式:函數語言程式設計。
函數語言程式設計是宣告式程式設計的子範式。與指令式程式設計相反,函數語言程式設計不會改變程式的內部狀態。在指令式程式設計中,函數更多地被視爲指令、例程或過程的序列。它們不僅依賴於儲存在記憶體中的狀態,而且還可以改變該狀態。這樣,根據當前程式的狀態,使用相同參數呼叫命令式函數可能會產生不同的結果,與此同時,被執行的函數更改了程式的變數。在函數語言程式設計術語中,函數類似於數學函數,函數的輸出僅依賴於其參數,而不管程式的狀態如何,完全不受函數是何時執行的影響。矛盾的是,雖然指令式程式設計自計算機發明以來就存在,但函數語言程式設計的基本概念卻可以追溯到這之前。大多數函數式語言都是基於lambda演算,這是由數學家Alonzo Church於20世紀30年代建立的一種形式化數學邏輯系統。函數式語言在當時變得如此受歡迎的原因之一是它們可以輕鬆地在並行環境中執行,這與多執行緒不太一樣。函數式語言支援並行執行的關鍵在於它們的基本原理:函數僅依賴於輸入參數而不依賴於程式的狀態。也就是說,它們可以在任何地方執行,然後將多個並行執行的結果連線起來並進一步使用。