物件導向設計原則之合成複用原則
合成複用原則又稱為組合/聚合複用原則(Composition/Aggregate Reuse Principle, CARP),其定義如下:
合成複用原則(Composite Reuse Principle, CRP):儘量使用物件組合,而不是繼承來達到複用的目的。 |
合成複用原則就是在一個新的物件裡通過關聯關係(包括組合關係和聚合關係)來使用一些已有的物件,使之成為新物件的一部分;新物件通過委派呼叫已有物件的方法達到複用功能的目的。簡言之:複用時要儘量使用組合/聚合關係(關聯關係),少用繼承。
在物件導向設計中,可以通過兩種方法在不同的環境中複用已有的設計和實現,即通過組合/聚合關係或通過繼承,但首先應該考慮使用組合/聚合,組合/聚合可以使系統更加靈活,降低類與類之間的耦合度,一個類的變化對其他類造成的影響相對較少;其次才考慮繼承,在使用繼承時,需要嚴格遵循里氏代換原則,有效使用繼承會有助於對問題的理解,降低複雜度,而濫用繼承反而會增加系統構建和維護的難度以及系統的複雜度,因此需要慎重使用繼承複用。
通過繼承來進行復用的主要問題在於繼承複用會破壞系統的封裝性,因為繼承會將基類的實現細節暴露給子類,由於基類的內部細節通常對子類來說是可見的,所以這種複用又稱“白箱”複用,如果基類發生改變,那麼子類的實現也不得不發生改變;從基類繼承而來的實現是靜態的,不可能在執行時發生改變,沒有足夠的靈活性;而且繼承只能在有限的環境中使用(如類沒有宣告為不能被繼承)。
|
由於組合或聚合關係可以將已有的物件(也可稱為成員物件)納入到新物件中,使之成為新物件的一部分,因此新物件可以呼叫已有物件的功能,這樣做可以使得成員物件的內部實現細節對於新物件不可見,所以這種複用又稱為“黑箱”複用,相對繼承關係而言,其耦合度相對較低,成員物件的變化對新物件的影響不大,可以在新物件中根據實際需要有選擇性地呼叫成員物件的操作;合成複用可以在執行時動態進行,新物件可以動態地引用與成員物件型別相同的其他物件。
一般而言,如果兩個類之間是“Has-A”的關係應使用組合或聚合,如果是“Is-A”關係可使用繼承。"Is-A"是嚴格的分類學意義上的定義,意思是一個類是另一個類的"一種";而"Has-A"則不同,它表示某一個角色具有某一項責任。
下面通過一個簡單例項來加深對合成複用原則的理解:
Sunny軟體公司開發人員在初期的CRM系統設計中,考慮到客戶數量不多,系統採用MySQL作為資料庫,與資料庫操作有關的類如CustomerDAO類等都需要連線資料庫,連線資料庫的方法getConnection()封裝在DBUtil類中,由於需要重用DBUtil類的getConnection()方法,設計人員將CustomerDAO作為DBUtil類的子類,初始設計方案結構如圖1所示:
圖1 初始設計方案結構圖 隨著客戶數量的增加,系統決定升級為Oracle資料庫,因此需要增加一個新的OracleDBUtil類來連線Oracle資料庫,由於在初始設計方案中CustomerDAO和DBUtil之間是繼承關係,因此在更換資料庫連線方式時需要修改CustomerDAO類的原始碼,將CustomerDAO作為OracleDBUtil的子類,這將違反開閉原則。【當然也可以修改DBUtil類的原始碼,同樣會違反開閉原則。】 現使用合成複用原則對其進行重構。 |
根據合成複用原則,我們在實現複用時應該多用關聯,少用繼承。因此在本例項中我們可以使用關聯複用來取代繼承複用,重構後的結構如圖2所示:
圖2 重構後的結構圖
在圖2中,CustomerDAO和DBUtil之間的關係由繼承關係變為關聯關係,採用依賴注入的方式將DBUtil物件注入到CustomerDAO中,可以使用構造注入,也可以使用Setter注入。如果需要對DBUtil的功能進行擴充套件,可以通過其子類來實現,如通過子類OracleDBUtil來連線Oracle資料庫。由於CustomerDAO針對DBUtil程式設計,根據里氏代換原則,DBUtil子類的物件可以覆蓋DBUtil物件,只需在CustomerDAO中注入子類物件即可使用子類所擴充套件的方法。例如在CustomerDAO中注入OracleDBUtil物件,即可實現Oracle資料庫連線,原有程式碼無須進行修改,而且還可以很靈活地增加新的資料庫連線方式。
【作者:劉偉 http://blog.csdn.net/lovelion】
相關文章
- 軟體設計原則—合成複用原則
- 物件導向設計原則物件
- 開閉原則——物件導向程式設計原則物件程式設計
- 物件導向之六大設計原則物件
- The Principles of OOD 物件導向設計原則物件
- 2.物件導向設計原則物件
- 物件導向設計原則和模式物件模式
- 物件導向的基本設計原則物件
- 物件導向之 開閉原則物件
- 物件導向設計的六大原則(SOLID原則)-——里氏替換原則物件Solid
- Java中物件導向的設計原則Java物件
- 物件導向的編碼設計原則物件
- 物件導向OO原則物件
- 前端設計模式(0)物件導向&&設計原則前端設計模式物件
- 物件導向設計原則&設計模式分類物件設計模式
- 翻譯 | The Principles of OOD 物件導向設計原則物件
- 物件導向設計的6大原則物件
- SOLID:物件導向設計的前五項原則Solid物件
- 61條物件導向設計的經驗原則物件
- 七種常見的物件導向設計原則物件
- 實驗1:UML與物件導向程式設計原則物件程式設計
- 不止於物件導向的SOLID原則物件Solid
- 物件導向程式設計(OOP)的七大原則物件程式設計OOP
- 設計原則之【介面隔離原則】
- 物件導向的7大原則與23種設計模式物件設計模式
- 物件導向的六大原則物件
- 開發中濫用物件導向,你是否違背了程式設計原則物件程式設計
- 設計原則之【單一職責原則】
- 設計原則之【開放封閉原則】
- 設計原則之【依賴反轉原則】
- 設計原則之【裡式替換原則】
- 面象物件設計6大原則之四:介面隔離原則物件
- 面象物件設計6大原則之五:依賴倒置原則物件
- 物件導向設計的六大設計原則(附 Demo & UML類圖)物件
- 【設計模式筆記】(零)- 物件導向的六大原則設計模式筆記物件
- 設計模式:物件導向設計的六大原則 (絕對詳細)設計模式物件
- 設計模式之——物件導向5大基本原則設計模式物件
- 設計原則:開閉原則(OCP)
- 設計原則之【迪米特法則】