譯者 | 陳峻
審校 | 孫淑娟
在重構方面,Java主要有兩種主要方法,即:面向對象(object-oriented)和功能性(functional)。其中,前者幾乎是從Java第一版就存在了,而功能性始于2014年3月推出的Java 1.8。
1.面向對象和功能性方法
作為一種經典的面向對象語言,Java允許用戶創建靈活的對象結構。在Java 1.8出現了功能性特性之后,它不僅可以使用對象或方法,還可以使用lambdas(其本身是可執行代碼,https://dzone.com/articles/java-lambda-method-reference)進行各項操作。而在功能性的世界中,您可以像在OO的世界中使用對象那樣,去操作各種功能。
2.使用OO方法重構代碼
通過使用繼承或組合的方式來處理各種接口和類,您可以創建出各種可重用的通用方案,從而減少程序的代碼量,并提高可讀性。如果一個類滿足了如下的條件,那么它便可以在相同的公共結構中進行聯合:
- 具有相似的字段,并被識別為同一實體
- 有父/子(parent/children)關系
- 有相似目的的方法
3.使用功能性方法重構代碼
與OO方法不同,這種方法提取具有相同行為的代碼。例如,我們可以在如下兩個示例中識別出相似之處:
- 在具體實現上能夠返回相同類型
- 在具體實現上有相同的功能
4.使用兩種方法進行重構的示例
假設我們有一個小型應用程序,其功能向正式員工(Employee)和合同工(Contractor)支付工資。每次完成支付工資后,我們都會打印一份Employee報告,并以不同的格式顯示(https://dzone.com/articles/so-much-data-so-many-formats-a-conversion-service),即:正式員工為JSON格式,而合同工為XML格式。以下便是使用兩種方法重構的示例:
現在讓我們來看一下其默認結構:
5.重構類的結構
很明顯,Contractor可以成為Employee類的子類。同時,makePayment可以被覆蓋掉。當然,我們也可以創建一個Payable接口和提取makePayment的方法,不過讓我們在此保持簡單化。如下代碼段所示,在重構之后,我們產生了一些共同的字段,以及可重用的構造函數。
6.重構功能性
現在我們可以從功能性的角度,來回顧和發掘源代碼中的相似之處:
如上圖所示,從打印報告中可以看出,我們可以使用相同的方式來進行處理,即:傳遞一個對象,并返回一個字符串。因此,我們可以將代碼部分提取為一個可重用的功能,并將其動態地用于該業務的邏輯上。我們甚至可以將其拿到該業務的外部進行使用。
7.創建功能接口
為了判定正確的功能性接口(如,Predicate、Consumer、Function等),我們需要檢查自己的輸入和輸出。在本例中,我們得到的是一個Object,并需要將其轉換為String。
該接口是由功能函數提供的。為了更加便于理解,我們用serialize方法創建一個自有的Converter接口。其對應的代碼如下,具有極強的可讀性:
8.創建Lambda轉換器(Converter)功能性接口
下面,我們可以在功能性接口的基礎上,創建兩個轉換器:JSON和XML。它們都會去匹配已定義的簽名,即:對象輸入(Object Input)和字符串輸出(String Output)。
接著,讓我們在代碼中使用它們:
9.在Employee類中封裝轉換器
與前面的方法類似,我們可以將此功能封裝在Employee父類中,并在內部功能函數中使用它們。下圖展示了如何在Employee類中封裝轉換器:
10.審查最終版本
最后,我們初始化兩個employee類,并遍歷它們的支付執行情況和打印方法。
我們將最終得到:
- Employee父類中的Commons字段和方法被重用到了Contractor中
- 可以在無需更改Employee類的情況下,提取功能函數轉換器(我們可以在未來再做補充)
- 提取的功能函數可以在Employee類之外被重用
11.點評
總的說來,上述示例并不完美,且有待改進。例如,我們可以將Employee與Contractors類隱藏在接口的后面。您也可以試著去寫一個簡單的例子,以便只展示一些面對對象和功能特性。
當然,從嚴格意義上說,我創建的功能可能并非純功能。而一些開發人員往往堅持認為:在Java中只有純功能才是更好的。在此,我持保留意見。
12.小結
讓我們對上述內容小結一下:
使用面向對象的方法,我們可以將性質相似(similar-by-nature)的對象統一到同一個結構中。
使用功能性方法,我們則可以統一功能相似(similar-by-functionality)的代碼。
這兩種方法都能夠讓程序代碼的可讀性和可維護性得到顯著提高。
原文鏈接:https://dzone.com/articles/refactoring-java-application-object-oriented-and-f
譯者介紹
陳峻 (Julian Chen),51CTO社區編輯,具有十多年的IT項目實施經驗,善于對內外部資源與風險實施管控,專注傳播網絡與信息安全知識與經驗;持續以博文、專題和譯文等形式,分享前沿技術與新知;經常以線上、線下等方式,開展信息安全類培訓與授課。