軟考上午題終于考完了。三個趕考者都感覺不錯。檢查了2遍,提前30分鐘都出來了 。
小A,小B,小C樓下碰頭,相視一笑,輕松之感溢于言表。遂決定去吃面,以犒勞自己的肚子。
“老闆,我要蕃茄雞蛋面!”,“尖椒炸醬面!”,“蘇格蘭打鹵面!”。。。。。。“好嘞!”
面快出鍋了,“哎哎,老闆,怎麼我的面跟他的面一樣啊,就是換了一下鹵?”往面裡放鹵的服務員翻了小B一眼,不搭理。旁邊那個年長點的師傅笑了笑,說道“小兄弟兒,這你就不懂了吧。其實面都是一樣的,隻是換一下鹵罷了。”“哦哦,原來如此啊。”小B灰溜溜得端起面來跑開了。。。
面畢,小B實在是咽不下這口氣。就想在小C那兒“撈回點兒本來”。
“小C,面吃的怎麼樣啊?”小B陰陽怪氣的問道。
小C看着小B的表情,覺得有點不對勁,自己是不是又要上當了,但是又想不出來自己哪留有什麼“把柄”,然後就答道,
“還,還行吧,問這幹嘛??”
“嘿,你怕什麼呀。我考一個關于吃面的題目”
“嗨,我還以為什麼呢,随便考吧,哥是來者不拒。”小C心裡想到,就你那智商,能出什麼樣的難題呢,等着被鄙視吧。
“你感覺自家煮面和飯館煮面有什麼不同?”
“這還用問!感覺不同呗。自己煮面,自己累死了還得做飯,又是炒鹵,又是煮面的,最低也得折騰半小時吧。飯館多好啊,隻要吆喝一聲,人家都給你做好,端到你面前了。而且速度超快的。連這個都不知道。也對,就你那智商,好吧,我原諒你,哈哈哈哈”
“哼,别笑得太早了。同樣是面?你說為什麼感覺不同啊”
“呃,這個嘛,嗯,讓我想想”小C裝傻了。。。
“哈,有點意思哎。我給你說說看看對不。”小A憋不住了。接着說道,
“剛才小C說了,自家煮面,你必須自己做鹵,自己煮面。每次想吃面的時候,這兩步都是少不了的。但是面館不一樣啊。飯館鹵都是提前做好的。你點了面後,面館給你煮面,然後加上你要的鹵不就OK了嗎!而且速度超快。比自己做飯省事多了。”
“哦~,原來如此。”
“我說那會那個服務員像看白癡的一樣看我呀。”小B嘀咕道
“what,what!!原來你被吃癟了啊,哈哈”小C得意得捧腹大笑。
小A眼睛一轉,對即将要發飙的小B說道,
“既然是你提出來的,你說說飯館為什麼要這麼做呢?”
“呃,嗯,,,,我想,應該是為了更快捷,友善地友善使用者,同時提高自己的效率吧。”
“還有沒有别的?”
小B想了半天,搖來搖頭,“想不到了”
“提示一點,面館在增加新類型面的時候,是怎麼做的?”
“哦~~,我知道了,因為面差不多是一樣的,隻需要準備鹵就行了。”
“嗯,對的。其實面也是有不同的。比如說寬面,拉面,圓面。這樣一組合,新的類型的面就出爐了。”
“原來面館裡也有這麼大學問啊。”
“那是當然。365行,行行出狀元啊。先不說這個了,既然說道這個面了,那你用面向對象寫寫剛才我們讨論的這件事兒吧。”
“好。我試試吧”小B自信道。
既然是面向對象,那麼先把類找出來吧。首先有原料(Material),下分為面(Noodles)和鹵(Halogen)。面有寬面條(WideNoodles),窄面條(NarrowNoodles)等多種類型,鹵菜有蕃茄雞蛋鹵(TomatoAndEgg),茄子豆瓣醬(AubergineBeanPaste)等多種鹵菜。 蕃茄雞蛋面類(TomatoEggNoodles)為蕃茄雞蛋鹵和寬面構成,而蘇格蘭打鹵面(ScotlandNoodles)則是有茄子
豆瓣醬和窄面構成的。
先畫出UML圖:
uml圖1.0版

“看看怎麼樣啊”,小B得瑟的說道。
“你有沒有考慮代碼的實作呢?”小A用看白癡的眼神掃了小B一眼,“除了C++,還有幾個面向對象的有多繼承啊!”
“呃,這個,失誤失誤,我馬上改!”
“别急啊,還有錯誤呢,蕃茄雞蛋面有兩部分構成,那肯定是用聚合或者是組合啊,不應該用繼承的”小A提醒道。
“哦,原來如此,我說怎麼感覺有點不對勁呢,等着吧”
5分鐘過後。。。
“哦,終于出來了,看看這次怎麼樣啊。”
uml圖2.0.版
“蕃茄雞蛋面和蘇格蘭打鹵面的組成關系也畫出來了。嗯不錯,不過還有一點不對勁。假如我現在加一個新類型的面——蕃茄雞蛋鹵面(窄面),你怎麼加”
“那就從面條類裡泛化一個蕃茄雞蛋鹵面(窄面)類,然後再在它上面加上與蕃茄雞蛋鹵和窄面的組合關系”
“那如果我現在面館開10個分面館,每個分面館新增10樣類,你是不是這100種面都要重新添加一遍面和鹵的組合關系吧。”
“那我還不得累死啊,這種活幹不得!”小B惶恐的說道。
“不管累,當你畫出UML圖的時候,能把你亂死。成品面與具體的面類型和鹵菜類型的耦合性就太高了。想辦法松散這些耦合。”
“那怎麼辦呢?”小B焦急的問道。
“呃,提醒你一點,你先對比一下你這兩版UML各自的特點。”
“第一幅圖繼承關系比較明顯,第二幅圖則利用了組合關系,使其繼承關系簡單化了”
“如果你把這兩個圖合成一個圖呢?”
“這,這,怎麼合啊。”
“看來還得我出馬啊,看着昂”
UML圖3.0版
“不管什麼打鹵面,都抽象于鹵面類。鹵面類由面條類和鹵菜類組成。面條類和鹵菜類都有各自的子類。”
“這個圖好面熟啊。讓我想想昂。哦,對了,這不是橋接模式嗎!”
“是的,不過這樣做有什麼好處呢?”
“這樣做有幾個好處,第一,松散耦合。具體的打鹵面不再與具體的面類型和鹵類型直接關聯,松散了它們之間的耦合;第二,在變化方面,具體的打鹵面, 具體的面類型和具體的鹵類型各自的變化,互不影響”
“這樣我在開分面館的時候就不用畫那麼多關系了,添加新類型的打鹵面不再成為難事。果然很厲害。哈哈哈哈”小B得瑟的笑着,好像他真的要開面館似的。
“對頭!這就滿足了開閉原則,不用去修改,隻需要添加即可。執行個體化具體的打鹵面時,在用戶端指定一下要哪種面,哪個鹵即可。”小A接着說,
“其實這裡面最重要的是利用聚合組合關系,松散了耦合,使得抽象不再依賴于具體,而具體要依賴于抽象。”
“哦,對哦。設計模式果然牛X。”
“代碼留在晚上再寫吧,早點休息,下午還有考試呢!”小A看着一臉丫丫的小B,提醒道。
“哦哦,差點忘了還有考試了。希望下午碰到橋接模式,那我就。。。”小B繼續陷入丫丫ing。
小A搖搖頭,不再理睬小B,推開霸占自己床鋪的小C,休息去了。
面條類及子類
鹵菜類及子類
打鹵面類及子類
用戶端代碼:
運作結果: