這篇文章主要介紹了合成聚合復用原則,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧
合成聚合復用原則
#合成復用原則又稱為組合/聚合復用原則(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資料庫連接,原有程式碼無須進行修改,而且還可以很靈活地增加新的資料庫連接方式。
以上是Java中合成聚合復用原則的圖文詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!