【三】、面向對象設計原則
面向對象設計原則概述
- 可維護性:指軟體能夠被了解、改正、适應及擴充的難易程度。
- 可複用性:指軟體能夠被重複使用的難易程度。
- 面向對象設計的目标之一在于支援可維護性複用,一方面需要實作設計方案或者源代碼的複用,另一方面要確定系統能夠易于擴充和修改,具有良好的可維護性。
- 面向對象設計原則為支援可維護性複用而誕生。
- 指導性原則,非強制性原則。
- 每一個設計模式都符合一個或多個面向對象設計原則,面向對象設計原則是用于評價一個設計模式的使用效果的重要名額之一。

單一職責原則
單一職責原則定義
- 單一職責原則是最簡單的面向對象設計原則,用于控制類的粒度大小。
單一職責原則:一個對象應該隻包含單一的職責,并且該職責被完整地封裝在一個類中。
- 就一個類而言,應該僅有一個引起它變化的原因。
單一職責原則分析
- 一個類(大到子產品,小到方法)承擔的職責越多,它被複用的可能性就越小
- 當一個職責變化時,可能會影響其他職責的運作
- 将這些職責進行分離,将不同的職責封裝在不同的類中
- 将不同的變化原因封裝在不同的類中
- 單一職責原則是實作高内聚、低耦合的指導方針。
執行個體說明
- 某基于Java的C/S系統的“登入功能”通過如下登入類(Login)實作:
- 現使用單一職責原則對其進行重構。
開閉原則
開閉原則定義
- 開閉原則是面向對象的可複用設計的第一塊基石,是最重要的面向對象設計原則。
開閉原則:軟體實體應當對擴充開放,對修改關閉。
開閉原則分析
- 開閉原則由Bertrand Meyer于1988年提出。
- 在開閉原則的定義中,軟體實體可以是一個軟體子產品、一個由多個類組成的局部結構或一個獨立的類
- 開閉原則是指軟體實體應盡量在不修改原有代碼的情況下進行擴充
- 抽象化是開閉原則的關鍵
- 相對穩定的抽象層+靈活的具體層
- 對可變性封裝原則:找到系統的可變因素并将其封裝起來
開閉原則執行個體
- 某圖形界面系統提供了各種不同形狀的按鈕,用戶端代碼可針對這些按鈕進行程式設計,使用者可能會改變需求要求使用不同的按鈕,原始設計方案如圖所示:
- 現對該系統進行重構,使之滿足開閉原則的要求。
裡氏代換原則
裡氏代換原則定義
- 裡氏代換原則:所有引用基類的地方必須能透明地使用其子類的對象。
裡氏代換原則分析
- 在軟體中将一個基類對象替換成它的子類對象,程式将不會産生任何錯誤和異常。
- 反過來則不一定成立,如果一個軟體實體使用的是一個子類對象的話,那麼它不一定能夠使用基類對象。
- 在程式中盡量使用基類類型來對對象進行定義,而在運作時再确定其子類類型。
裡氏代換原則執行個體
- 某系統需要實作對重要資料(如使用者密碼)的加密處理,在資料操作類中需要調用加密類中定義的加密算法,系統提供了兩個不同的加密類,CipherA和CipherB,它們實作不同的加密方法,在DataOperator中可以選擇其中的一個實作加密操作。如圖所示:
執行個體說明:
- 如果需要更換一個加密算法類或者增加并使用一個新的加密算法類,如将CipherA改為CipherB,則需要修改客戶類Client和資料操作類DataOperator的源代碼,違背了開閉原則。
- 現使用裡氏代換原則對其進行重構,使得系統可以靈活擴充,符合開閉原則。
依賴倒轉原則
依賴倒轉原則定義
- 依賴倒轉原則:高層子產品不應該依賴低層子產品,它們都應該依賴抽象。抽象不應該依賴于細節,細節應該依賴于抽象。
- 要針對接口程式設計,不要針對實作程式設計。
依賴倒轉原則分析
- 在程式代碼中傳遞參數時或在關聯關系中,盡量引用層次高的抽象層類,即使用接口和抽象類進行變量類型聲明、參數類型聲明、方法傳回類型聲明,以及資料類型的轉換等。
- 在程式中盡量使用抽象層進行程式設計,而将具體類寫在配置檔案中。
- 針對抽象層程式設計,将具體類的對象通過依賴注入的方式注入到其他對象。
- 構造注入
- 設值注入(Setter注入)
- 接口注入
依賴倒轉原則執行個體
- 某系統提供一個資料轉換子產品,可以将來自不同資料源的資料轉換成多種格式,如可以轉換來自資料庫的資料、也可以轉換來自文本檔案的資料,轉換後的格式可以是XML檔案、也可以是XLS檔案等。
- 由于需求的變化,該系統可能需要增加新的資料源或者新的檔案格式,每增加一個新的類型的資料源或者新的類型的檔案格式,客戶類MainClass都需要修改源代碼,以便使用新的類,但違背了開閉原則。現使用依賴倒轉原則對其進行重構。
接口隔離原則
接口隔離原則定義
- 接口隔離原則:用戶端不應該依賴那些它不需要的接口
接口隔離原則分析
- 當一個接口太大時,需要将它分割成一些更細小的接口
- 使用該接口的用戶端僅需知道與之相關的方法即可
- 每一個接口應該承擔一種相對獨立的角色,不幹不該幹的事,該幹的事都要幹。
- “接口”定義(1):一個類型所提供的所有方法特征的集合。一個接口代表一個角色,每個角色都有它特定的一個接口,角色隔離原則。
- “接口”定義(2):俠義的特定語言的接口。接口僅僅提供用戶端需要的行為,用戶端不需要的行為則隐藏起來,應該為用戶端提供盡可能小的單獨的接口,而不需要提供大的總接口,每個接口中隻包含一個用戶端所需的方法,“定制服務”。
接口隔離原則執行個體
- 下圖展示了一個擁有多個客戶類的系統,在系統中定義了一個巨大的接口(胖接口)AbstractService來服務所有的客戶類。可以使用接口隔離原則對其進行重構。
合成複用原則
合成複用原則定義
- 合成複用原則又稱為組合/聚合複用原則
- 合成複用原則:優先使用對象組合,而不是繼承來達到複用的目的。
合成複用原則分析
- 合成複用原則就是在一個新的對象裡通過關聯關系(包括組合關系和聚合關系)來使用一些已有的對象,使之成為新對象的一部分。
- 新對象通過委派調用已有對象的方法達到複用功能的目的。
- 複用時要盡量使用組合/聚合關系(關聯關系),少用繼承。
- 繼承複用:實作簡單,易于擴充。破壞系統的封裝性;從基類繼承而來的實作是靜态的,不可能在運作時發生改變,沒有足夠的靈活性;隻能在有限的環境中使用。(“白箱”複用)
- 組合/聚合複用:耦合度相對較低,有選擇性地調用成員對象的操作;可以在運作時動态進行,新對象可以動态地引用與成員對象類型相同的其他對象。(“黑箱”複用)
合成複用原則執行個體
- 某教學管理系統部分資料庫通路類設計如圖所示:
- 如果需要更換資料庫連接配接方式,如原來采用JDBC連接配接資料庫,現在采用資料庫連接配接池連接配接,則需要修改DBUtil類源代碼。如果StudentDAO采用JDBC連接配接,但是TeacherDAO采用連接配接池連接配接,則需要增加一個新的DBUtil類,并修改StudentDAO或TeacherDAO的源代碼,使之繼承新的資料庫連接配接類,這将違背開閉原則,系統擴充性較差。
- 現使用合成複用原則對其進行重構。
迪米特法則
迪米特法則定義
- 迪米特法則又稱為最少知識原則。
- 迪米特法則:每一個軟體機關對其他的機關都隻有最少的知識,而且局限于那些與本機關密切相關的軟體機關。
迪米特法則分析
迪米特法則來自于1987年美國東北大學一個名為“Demeter”的研究項目。 迪米特法則要求一個軟體實體應當盡可能少地與其他實體發生互相作用 應用迪米特法則可降低系統的耦合度,使類與類之間保持松散的耦合關系。 迪米特法則要求在設計系統時,應當盡量減少對象之間的互動 。如果兩個對象之間不必彼此直接通信,那麼這兩個對象就不應該發生任何直接的互相作用 。如果其中一個對象需要調用另一個對象的方法,可以通過“第三者”轉發這個調用 * 通過引入一個合理的“第三者”(中間類)來降低現有對象之間的耦合度。
迪米特法則執行個體
- 某系統界面類(如Form1、Form2等類)與資料通路類(如DAO1、DAO2等類)之間的調用關系較為複雜,如圖所示: