在 Design Pattern 的書裡,大概都會提到「多用合成、少用繼承」,不過具體來說到底繼承會產生什麼問題、合成又能解決什麼問題,一直到現在才有比較明確的感覺。但由於不太擅長描述這種有些抽象的問題,所以這裡就簡單地紀錄一些感覺到的重點,細節就請參閱底下的參考資料吧 XD。
首先,一切的源頭都是為了 OCP(Open-Closed Principle),也就是要盡可能滿足「對擴充開放、對修改封閉」這樣的準則。不過要滿足這個準則,其實會讓程式碼變得複雜,所以在選擇的過程也必須謹慎小心,盡可能只在真正需要的地方去滿足,而不要把這個準則套用到整個系統的每個角落 [1]。
在考量 OCP 的前提之下,由於繼承是屬於在編譯期間的關聯,因此很容易會導致使用繼承時,擴充會需要修改既有的程式碼。這就會導致違反了 OCP 當中的「對修改封閉」的要件。
另外繼承在可能性眾多的情況,也很容易導致子類別的數量爆炸,造成日後維護的困難。
反過來說,合成是屬於在執行期間的關聯,因此較有機會可以避免上述的問題。不過依據狀況的不同,合成也有可能形成子類別較多的現象,雖然不至於到數量爆炸的程度,但往往也會使得 API 變得難以掌握。這類的問題就得複合多種 Design Pattern 來隱藏問題,讓呼叫者不需要對細節有太多的了解。
不過同時也需要注意的是,雖然說概念上提到「少用繼承」,但使用合成其實並不表示完全不使用繼承。關鍵在於「不繼承行為」,但合成常常會需要「繼承型別」(然而這或許只限定在像是 Java 這類強型別的語言上)。
沒有留言:
張貼留言