合成復用原則又稱為組合/聚合復用原則(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資料庫連線,原有**無須進行修改,而且還可以很靈活地增加新的資料庫連線方式。
合成復用原則又稱為組合/聚合復用原則(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資料庫連線,原有**無須進行修改,而且還可以很靈活地增加新的資料庫連線方式。
物件導向設計原則之合成復用原則
合成復用原則又稱為組合 聚合復用原則 composition aggregate reuse principle,carp 其定義如下 合成復用原則 composite reuse principle,crp 盡量使用物件組合,而不是繼承來達到復用的目的。合成復用原則就是在乙個新的物件裡通過關聯關係...
物件導向設計原則 合成復用原則
合成復用原則又稱為組合 聚合復用原則 composition aggregate reuse principle,carp 其定義如下 合成復用原則 composite reuse principle,crp 盡量使用物件組合,而不是繼承來達到復用的目的。合成復用原則就是在乙個新的物件裡通過關聯關係...
物件導向設計原則之七 合成復用原則
合成復用原則又稱為組合 聚合復用原則 composition aggregate reuse principle,carp 其定義如下 合成復用原則 composite reuse principle,crp 盡量使用物件組合,而不是繼承來達到復用的目的。合成復用原則就是在乙個新的物件裡通過關聯關係...