- 貫穿設計模式:用一個電商項目詳解設計模式
- 偉山育琪
- 833字
- 2024-12-28 11:44:57
1.4 合成復用原則
合成復用原則,又稱為組合/聚合復用原則(Composition/Aggregate Reuse Principle,CARP)。該原則要求在代碼復用時,要盡量先使用組合或者聚合等關聯關系(也就是包含、使用屬性成員的方式)來實現,其次才考慮使用繼承關系來實現。
合成復用原則,在部分資料中將其稱之為設計模式的第七個原則,所以部分資料中會有“設計模式七大原則”的字眼。對于設計模式原則而言,六大原則也好,七大原則也罷,兩種說法并無對錯之分。隨著設計模式的應用越來越多,將來可能還會有其他原則的出現。正因為如此,由于各種資料對設計模式原則介紹的不統一性,所以筆者沒有將該原則納入章節重點。雖然沒有納入章節重點,但筆者依然會在此小節對合成復用原則進行詳細的說明。
為了更加清晰地說明合成復用原則,筆者提出了一個常見的小問題:“我們在SpringMVC或SpringBoot項目的接口開發過程中,Controller層如何調用Service層的方法呢?”
相信大部分讀者都能夠迅速地給出答案,使用@Autowired注解,將Service注入到Controller就可以了,正確的代碼示例如下:

從以上代碼示例中可以看出,我們通過@Autowired注解將UserService注入到了UserController,我們可以隨時對UserService中的方法進行調用,這就是合成復用原則之中提到的“要盡量先使用組合或者聚合等關聯關系(也就是包含,使用屬性成員的方式)來實現”。依賴注入,就是合成復用原則最具代表性、最經典的案例體現。
大家試想一下,如果我們采用繼承的方式進行UserService方法調用,就會出現如下“毀三觀”的代碼。

雖然依然能夠達成我們調用UserService中方法的目的,但是這樣的代碼書寫方式無疑增大了UserController和UserService的耦合性,而且違背了我們長久以來的開發方式。部分讀者可能會有疑問:“難道合成復用原則下,所有的代碼都不使用繼承了嗎?各種源碼中,很多代碼的類繼承、接口實現都是有問題的嗎?”解答這些疑問,首先要理解類繼承和接口實現的核心思想,兩個能夠成為父子關系的類或接口必然有相似的特性,或者有擴展的需要,如子類LinkedHashMap與父類HashMap,再如DefaultListableBeanFactory子類與BeanFactory接口的關系,都是同宗同族,且子類都進行了擴展操作。然而以上代碼示例中,僅僅為了調用UserService的方法而進行的繼承,則是一種錯誤的方式。