設計模式推演——組合與繼承

OO中,複用代碼可以有組合和繼承兩種方式,正如廣大人民羣衆所論述的,儘可能使用組合。

這裏我再不厭其煩的說明一下理由:

1. 組合比繼承在框架結構上要簡單,不會造成過深的繼承層次。

2. 組合是黑盒重用,抽象層次更高。


其實上面這兩條我覺得也沒啥,重點還是下面三條:

3.組合可以在運行時動態選擇複用的對象,而繼承不行。直接上圖,相信您看一眼就明白了

當Stack複用Sequence對象來實現自己的行爲時,只要是序列型容器就可以了,具體可以是Vector,List。

最重要的是,具體選擇Vector or List對象,可以在運行時由成員變量sequence的值決定,而變量的值是可以動態改變的



4. 使用繼承方式,子類必須被迫接收所有父類公有方法,但是實際上,有些方法子類是不需要的,甚至這些方法會對子類有害。

顯然,使用繼承的方式實現Stack,雖然push 和 pop有了正確的行爲,但是Vector的行爲在Stack中仍然是可以合法調用的。你可能覺得這些多餘的方法無關緊要,不去管他就可以了。但是別有用心的黑客呢,閒着蛋疼的某個屌絲呢?系統說不定就因此崩了


5. 當對象有多個行爲或屬性時,組合更容易複用。

(原諒我這裏私自把鴨改成雞,因爲我覺得這樣更能激發想象空間)


使用繼承的方式實現, 叫的行爲並不能被很好複用,“會叫不會飛的雞”與“會叫又會飛的雞” 在 叫的行爲上是相同的,但是這裏無法複用,只能在這兩個子類中分別實現“會叫”這個行爲。 如果客戶又要求你增加一個會叫又會舞的雞,你又得重複實現一遍“會叫”的行爲。



使用組合的方式就完全是"名副其實"了, 這裏複用,只是簡單的搭積木。這裏實際體現的是單一職責原則。



當然,組合的使用是有條件的,因爲是黑箱複用,所以當有些行爲無法通過對象的共有方法實現時,就只能依賴繼承(可以有保護方法,典型的如模板方法)。

另外,對於理由5,如果飛的行爲與雞本身耦合很大,其實現必須依賴於雞的私有或者保護成員,那麼也是不可能應用組合的。


無論如何,只要有條件,我們應儘可能使用組合。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章