設計模式深入淺出-削尖你的鉛筆系列1
最近開始看Head First in Design Pattern,不過要看的東西有點多,所以慢慢看,也細細品嚐。(這本大概一堆人都看過了)
以下是他提出的一些小作業,題目是書上的,最近在家裡也滿難找到白紙的,所以用這個來
寫寫作業,題目下的見解是我大概的想法,也藉此理清看看我的想法對不對
當然現實coding的時候,總是更難上加難,而不是只有鴨子跟汽車而己。不過原理都有問題的話,就笑掉別人大牙了
所以別笑這個例子了啦
題目是這樣的
有一個鴨子的類別
Class Duck{
swin();
show();
}
情境是,假如你認為,所有的鴨子(甚至是鳥類好了),都定義了飛行,卻讓其他所有"鴨類"都繼承鴨子,
Class Duck{
swin();
show();
fly();
}
但問題發生在…玩具鴨會飛嗎?假如又定義了鴨子會叫,那木頭鴨會叫嗎?不過橡皮鴨會叫又不會飛!....
當然這只是書上的例子,這是要明白,對程式做局部的修改,就會影響到全面性的東西
在未來或許玩具鴨真的飛起來了,卻不合你Conceptual的概念,不然就是維護上,這個繼承的結局好像並不完美
Think about it..若利用繼承提供鴨子行為,會導致下列哪些缺點?
- 1.程式碼在多個次類別重覆?
程式碼重覆?會嗎?繼承不就是為了節省程式碼嗎?若子類別,都有同樣的行為,例如,汽車與卡車繼承了車子類別,那麼我可以在"車"類別中定義他有四個輪子的屬性,以及他們都有發動引擎的行為(我承認這個例子很老),不過繼承的好處之一不就是為了避免程式碼的開發嗎?當然書上的例子是指鴨子類別都有會飛的行為的話,我就可以在鴨子類別中定義飛的行為就好了,這樣,繼承的鴨子都會飛的很高了!
- 2.執行期的行為不容易改變?
執行期的行為是指,假如我現在一台汽車繼承了車類別,我在製造(new)了一台汽車以後,想說汽車的類別該加一個音樂播放機的功能。這樣我只要在汽車類別去定義播放音樂的行為就好了,再者,我可以透過多型,例如,多載(廣義下的多型)的方式定義不同參數所對應的不同行為,就像,假如現在放入了卡帶,自然就是播放卡帶的行為啦,而放入了CD就可以聽到更高音質的音樂囉。因此正因為繼承,我可以對繼承下來的汽車,施行多樣化的行為與功能囉!
- 3.我們不能讓鴨子跳舞。?
可以,而且跟定義鴨子飛行一樣簡單,寫在超類別,所有繼承的鴨子就能跳來跳來去了!還可以讓鴨子自動變成鴨肉大餐,不過…一樣的問題,要看合不合你的概念性。
- 4.難以得知所有鴨子的全部行為?
若一開始不知道有玩具鴨的存在,你可能真的會將飛行加上去,當玩具鴨出現的時候,你會把他歸類到玩具,而不是鴨子,我會說我哪知道玩具鴨的存在啊!!不過這個例子是在告訴我們,局部的修改會影響到全面性的程式。正是指我們可能接到一個需求,但是為了快速的實作出功能,就隨意加在超類別中,結果沒有在掃視其他被影響,但是卻沒有能力做該行為的子類別,這正是一個可怕的問題!(產生實例時,結果出現一些無法理解的事情,甚至是error)
- 5.鴨子不能同時又飛又叫?
當然可以!只要給他們定義,他們就會又飛又叫,當然你也可以將他們定義的只會飛不會叫,你就可以透過重載(Override),在玩具鴨重載了一個fly的方法,但是不要做任何程式的撰寫就好啦。不過,當類別有不斷變動的需求的話,這樣每次就要無止盡的檢視並可能需要重載覆寫之前寫在超類別的功能,這樣不是勞心勞力...而且假如
現在有二三十個次類別的時候,那改也改死了,即使只有一點點。
- 6.改變會牽一髮動全身,造成其他鴨子不想要的改變。
這正是這次題目想要說的,就是明明飛行不是所有鴨子都可以做到的,不過我們定義在超類別後,仍要去將次類別
所無法實現的次類別去進行重載覆寫。不然做出來不該做的行為(例如一般使用者擁有了管理者的行為)就不是繼承的美意了!
因此我想答案應該是4以及6囉!
Keep go on...Next...
(這一次介面也不是解決方案,即使介面可以排除掉會飛的玩具鴨問題就是了,不過程式碼就會因此無法再利用,介面也是有很多缺點滴,下次再聊,這次不是聊OOP的優點..)