面向?qū)ο笤O(shè)計(jì)
自從面向?qū)ο缶幊陶Z(yǔ)言在軟件開(kāi)發(fā)中成為主流之后,遵循面向?qū)ο蠹夹g(shù)特點(diǎn)的軟件設(shè)計(jì)工作,也一并發(fā)展了起來(lái)。
首先要提出一個(gè)問(wèn)題,就是設(shè)計(jì)的工作是要做什么?

它包括的范圍其實(shí)是很廣泛的,從搜集用戶需求,進(jìn)行業(yè)務(wù)分析,到繪制系統(tǒng)流程圖等。可以說(shuō),在動(dòng)手編寫(xiě)代碼之前,程序員要做的都屬于設(shè)計(jì)工作。
就像建造房屋一樣,先確定要造的房屋類(lèi)型,然后是選址,設(shè)計(jì)樣式。最后工程師帶領(lǐng)施工隊(duì)按照設(shè)計(jì)圖紙將房子造出來(lái)。
而面向?qū)ο蠹夹g(shù),因?yàn)槠浞庋b、繼承、多態(tài)等特點(diǎn),在對(duì)現(xiàn)實(shí)世界建模時(shí),可以方便地以自然思維將事物抽象為計(jì)算機(jī)可處理的數(shù)據(jù)。關(guān)于面向?qū)ο蠹夹g(shù)的詳細(xì)說(shuō)明,可參看往期文章學(xué)好面向?qū)ο缶幊陶Z(yǔ)言的關(guān)鍵,在于掌握它們的共通結(jié)構(gòu)與特性 。
要做的事情清楚了,思維工具也有了,接下來(lái)就是如何將工作成果表述出來(lái)。一個(gè)相當(dāng)有力的工具就是統(tǒng)一建模語(yǔ)言(Unified Modeling Language,簡(jiǎn)稱UML),下一節(jié)會(huì)對(duì)其進(jìn)行入門(mén)級(jí)的介紹。
最后會(huì)以一個(gè)示例講述在面向?qū)ο笤O(shè)計(jì)中,如何應(yīng)用UML來(lái)完成建模工作。
UML概述
UML雖然也是一門(mén)“語(yǔ)言”,但它其實(shí)是一套圖形化的符號(hào)系統(tǒng)。UML最主要的作用,就是在現(xiàn)實(shí)世界與程序代碼之間建起一座橋梁。
這就是UML的“統(tǒng)一”所要求的,所以它的各種圖形都有著嚴(yán)格的定義。包括形狀、連接線的方向、方法與屬性的標(biāo)明等。
遵循統(tǒng)一標(biāo)準(zhǔn)的好處,就是方便了溝通。當(dāng)設(shè)計(jì)的各個(gè)階段的成果繪制成UML圖保存下來(lái)時(shí),那么無(wú)論是團(tuán)隊(duì)內(nèi)部協(xié)作,還是對(duì)外交流,大家都省去了學(xué)習(xí)符號(hào)表示法的時(shí)間,可以直接掌握設(shè)計(jì)意圖。

UML 2 定義了13種圖形,我們可以了解一下,對(duì)于重要的圖形,會(huì)給出圖示。所有圖形采用bouml工具繪制。
用例圖:表示系統(tǒng)提供的功能和使用者之間的關(guān)系。

用例圖
類(lèi)圖:表示類(lèi)的規(guī)格和類(lèi)之間的關(guān)系。

類(lèi)圖
對(duì)象圖:表示實(shí)例之間的關(guān)系。

對(duì)象圖
時(shí)序圖:將實(shí)例之間的相互作用表示為時(shí)間序列。

時(shí)序圖
活動(dòng)圖:表示一系列處理中的控制流程。

活動(dòng)圖
通信圖:將實(shí)例之間的相互作用表示為組織結(jié)構(gòu)。

通信圖
狀態(tài)機(jī)圖:表示實(shí)例的狀態(tài)變化。

狀態(tài)機(jī)圖
組件圖:表示文件和數(shù)據(jù)庫(kù)、進(jìn)程和線程等軟件的實(shí)現(xiàn)結(jié)構(gòu)。

組件圖
部署圖:表示硬件、網(wǎng)絡(luò)等系統(tǒng)的物理結(jié)構(gòu)。

部署圖
復(fù)合結(jié)構(gòu)圖:表示具有整體-部分結(jié)構(gòu)的類(lèi)的運(yùn)行時(shí)結(jié)構(gòu)。
包圖:表示包之間的關(guān)系。
交互概覽圖:將根據(jù)不同條件執(zhí)行不同動(dòng)作的時(shí)序圖放到活動(dòng)圖中進(jìn)行表示。
定時(shí)圖:采用帶數(shù)字刻度的時(shí)間軸來(lái)表示實(shí)例之間的狀態(tài)遷移和相互作用。
建模
什么是統(tǒng)一說(shuō)了,用到的圖形語(yǔ)言也說(shuō)了,最后就得說(shuō)一說(shuō)怎么建模了。我們進(jìn)行面向?qū)ο蟮脑O(shè)計(jì)工作,終歸是要讓計(jì)算機(jī)來(lái)幫助我們處理那些繁瑣、重復(fù)性的工作。
那么,接下來(lái)我們就以一個(gè)租車(chē)業(yè)務(wù)為示例,使用UML工具進(jìn)行設(shè)計(jì)過(guò)程吧。我們模仿實(shí)現(xiàn)一個(gè)線上租車(chē)應(yīng)用,為了簡(jiǎn)化討論,只提及最關(guān)鍵的幾個(gè)功能點(diǎn)。
業(yè)務(wù)分析階段
用戶想要租一輛車(chē)開(kāi),第一步是要先挑選合適的車(chē)。例如是城市代步,還是郊游遠(yuǎn)行等。選好車(chē)之后,就是預(yù)約下單。用戶辦理好手續(xù),將車(chē)開(kāi)走使用,最后完成歸還手續(xù)。
那么,對(duì)以上場(chǎng)景分析之后,可以通過(guò)活動(dòng)圖把整體流程畫(huà)出來(lái)。

租車(chē)業(yè)務(wù)整體流程
需求定義階段
從上述業(yè)務(wù)分析可知,這個(gè)線上租車(chē)系統(tǒng)可以承擔(dān)的自動(dòng)化工作,包括展示車(chē)輛信息,處理預(yù)訂訂單,車(chē)輛出庫(kù),跟蹤車(chē)輛行駛情況,以及車(chē)輛歸還入庫(kù)這些功能。
使用用例圖展示客戶與服務(wù)提供商可以使用的功能。

租車(chē)業(yè)務(wù)功能用例
系統(tǒng)設(shè)計(jì)階段
系統(tǒng)功能點(diǎn)梳理出來(lái)之后,就是對(duì)系統(tǒng)中的各個(gè)關(guān)鍵對(duì)象進(jìn)行定義。車(chē)輛對(duì)象(Car)是基本單元,所有的租賃業(yè)務(wù)都要圍繞它展開(kāi)。接下來(lái)是汽車(chē)展示對(duì)象(ShowCar),它可以從車(chē)輛對(duì)象取得可供展示的信息,例如車(chē)型、廠商、顏色等。
當(dāng)用戶選定車(chē)輛之后,就可以執(zhí)行預(yù)訂功能。租賃管理對(duì)象(RentServer)將會(huì)接受訂單、收取押金和預(yù)付款。用戶取車(chē)時(shí)RentServer則進(jìn)行出庫(kù)處理,并通知車(chē)輛跟蹤對(duì)象(TraceCar)持續(xù)監(jiān)控車(chē)輛運(yùn)行情況。
用戶使用完,歸還車(chē)輛時(shí),RentServer則從TraceCar查詢車(chē)況,確認(rèn)無(wú)誤后則執(zhí)行入庫(kù)處理,退還用戶押金。
據(jù)以上描述,我們可以先畫(huà)出類(lèi)圖。

租車(chē)業(yè)務(wù)類(lèi)圖
從上圖可以看到,Car作為系統(tǒng)的基本單元,被其他類(lèi)聚合使用。關(guān)于聚合,這是一種整體與個(gè)體之間的關(guān)系,即has-a關(guān)系。而組合則要更高一級(jí),是包含關(guān)系。例如汽車(chē)與發(fā)動(dòng)機(jī)就是組合關(guān)系,因?yàn)殡x開(kāi)了發(fā)動(dòng)機(jī),汽車(chē)就不可用了。
關(guān)聯(lián)關(guān)系則比聚合還要弱一級(jí),但需要注意的是,在程序代碼中,關(guān)聯(lián)與聚合的語(yǔ)法是一樣的,它們的差異是存在于語(yǔ)義上的。這也是UML設(shè)計(jì)能比代碼包含更多信息的優(yōu)勢(shì)。
類(lèi)圖表示的是類(lèi)之間的靜態(tài)關(guān)系,要看到對(duì)象實(shí)例之間的消息調(diào)用,則還要使用時(shí)序圖。下面分步驟繪制,先看預(yù)訂流程的時(shí)序圖。

租車(chē)預(yù)訂時(shí)序圖
接下來(lái)是用戶歸還車(chē)輛的時(shí)序圖。

歸還車(chē)輛時(shí)序圖
對(duì)象間的交互已經(jīng)有了,接下來(lái)就是具體方法的實(shí)現(xiàn)過(guò)程。說(shuō)明方法的執(zhí)行過(guò)程,使用活動(dòng)圖比較適合。下面選取CheckOut方法,對(duì)其繪制活動(dòng)圖進(jìn)行說(shuō)明。

CheckOut流程活動(dòng)圖
至于其他功能,有興趣的同學(xué)們可以自行繪制。實(shí)際項(xiàng)目所產(chǎn)出的UML設(shè)計(jì),則會(huì)復(fù)雜得多,但只要掌握好面向?qū)ο笤O(shè)計(jì)的理念,以及UML工具的圖形細(xì)節(jié),那么無(wú)論是閱讀既有設(shè)計(jì),還是自己通過(guò)繪圖表達(dá)設(shè)計(jì)想法,都能夠做到得心應(yīng)手。