《軟件詳細設(shè)計教程》課件第10章_第1頁
《軟件詳細設(shè)計教程》課件第10章_第2頁
《軟件詳細設(shè)計教程》課件第10章_第3頁
《軟件詳細設(shè)計教程》課件第10章_第4頁
《軟件詳細設(shè)計教程》課件第10章_第5頁
已閱讀5頁,還剩116頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第10章面向?qū)ο笤O(shè)計10.1面向?qū)ο笤O(shè)計的準則10.2啟發(fā)規(guī)則10.3系統(tǒng)分解10.4設(shè)計問題域子系統(tǒng)10.5設(shè)計人機交互子系統(tǒng)10.6設(shè)計任務(wù)管理子系統(tǒng)10.7設(shè)計數(shù)據(jù)管理子系統(tǒng)10.8設(shè)計類中的服務(wù)10.9設(shè)計關(guān)聯(lián)10.10設(shè)計優(yōu)化10.11面向?qū)ο蠓治雠c設(shè)計實例10.12小結(jié) 10.1面向?qū)ο笤O(shè)計的準則

所謂優(yōu)秀設(shè)計,就是權(quán)衡了各種因素,從而使得系統(tǒng)在其整個生命周期中的總開銷最小的設(shè)計。對大多數(shù)軟件系統(tǒng)而言,60%以上的軟件費用都用于軟件維護,因此,優(yōu)秀軟件設(shè)計的一個主要特點就是容易維護。

10.1.1模塊化

面向?qū)ο筌浖_發(fā)模式,很自然地支持了把系統(tǒng)分解成模塊的設(shè)計原理:對象就是模塊。它是把數(shù)據(jù)結(jié)構(gòu)和操作這些數(shù)據(jù)的方法緊密地結(jié)合在一起所構(gòu)成的模塊。10.1.2抽象

面向?qū)ο蠓椒ú粌H支持過程抽象,而且支持數(shù)據(jù)抽象。類實際上是一種抽象數(shù)據(jù)類型,它對外開放的公共接口構(gòu)成了類的規(guī)格說明(即協(xié)議),這種接口規(guī)定了外界可以使用的合法操作符,利用這些操作符可以對類實例中包含的數(shù)據(jù)進行操作。使用者無須知道這些操作符的實現(xiàn)算法和類中數(shù)據(jù)元素的具體表示方法,就可以通過這些操作符使用類中定義的數(shù)據(jù)。通常把這類抽象稱為規(guī)格說明抽象。

此外,某些面向?qū)ο蟮某绦蛟O(shè)計語言還支持參數(shù)化抽象。所謂參數(shù)化抽象,是指當描述類的規(guī)格說明時并不具體指定所要操作的數(shù)據(jù)類型,而是把數(shù)據(jù)類型作為參數(shù)。這使得類的抽象程度更高,應(yīng)用范圍更廣,可重用性更高。10.1.3信息隱藏

在面向?qū)ο蠓椒ㄖ?,信息隱藏通過對象的封裝性來實現(xiàn):類結(jié)構(gòu)分離了接口與實現(xiàn),從而支持了信息隱藏。對于類的用戶來說,屬性的表示方法和操作的實現(xiàn)算法都應(yīng)該是隱藏的。

10.1.4弱耦合

耦合指一個軟件結(jié)構(gòu)內(nèi)不同模塊之間互連的緊密程度。在面向?qū)ο蠓椒ㄖ?,對象是最基本的模塊,因此,耦合主要指不同對象之間相互關(guān)聯(lián)的緊密程度。弱耦合是優(yōu)秀設(shè)計的一個重要標準,因為這有助于使得系統(tǒng)中某一部分的變化對其他部分的影響降到最低程度。在理想情況下,對某一部分的理解、測試或修改,無須涉及系統(tǒng)的其他部分。如果一類對象過多地依賴其他類對象來完成自己的工作,則無疑給理解、測試或修改這個類帶來很大困難,而且還將大大降低該類的可重用性和可移植性。顯然,類之間的這種相互依賴關(guān)系是緊耦合的。

當然,對象不可能是完全孤立的,當兩個對象必須相互聯(lián)系、相互依賴時,應(yīng)該通過類的協(xié)議(即公共接口)實現(xiàn)耦合,而不應(yīng)該依賴于類的具體實現(xiàn)細節(jié)。

一般來說,對象之間的耦合可分為交互耦合和繼承耦合,下面分別討論它們。

1.交互耦合

如果對象之間的耦合通過消息連接來實現(xiàn),則這種耦合就是交互耦合。為使交互耦合盡可能松散,應(yīng)該遵守下述準則:

●盡量降低消息連接的復(fù)雜程度。應(yīng)該盡量減少消息中包含的參數(shù)個數(shù),降低參數(shù)的復(fù)雜程度。

●減少對象發(fā)送(或接收)的消息數(shù)。

2.繼承耦合

與交互耦合相反,應(yīng)該提高繼承耦合程度。繼承是一般化類與特殊類之間耦合的一種形式。從本質(zhì)上看,通過繼承關(guān)系結(jié)合起來的基類和派生類,構(gòu)成了系統(tǒng)中粒度更大的模塊。因此,它們彼此之間應(yīng)該結(jié)合得越緊密越好。

為獲得緊密的繼承耦合,特殊類應(yīng)該確實是對它的一般化類的一種具體化,也就是說,它們之間在邏輯上應(yīng)該存在“is-a”的關(guān)系。因此,如果一個派生類摒棄了其基類的許多屬性,則它們之間是松耦合的。在設(shè)計時應(yīng)該使特殊類盡量多繼承并使用其一般化類的屬性和服務(wù),從而更緊密地耦合到其一般化類。10.1.5強內(nèi)聚

內(nèi)聚衡量一個模塊內(nèi)各個元素彼此結(jié)合的緊密程度。也可以把內(nèi)聚定義為:設(shè)計中使用的一個構(gòu)件內(nèi)的各個元素,對完成一個定義明確的目的所做出的貢獻程度。在設(shè)計時應(yīng)該力求做到高內(nèi)聚。在面向?qū)ο笤O(shè)計中存在下述三種內(nèi)聚。

1.服務(wù)內(nèi)聚

一個服務(wù)應(yīng)該完成一個且僅完成一個功能。

2.類內(nèi)聚

設(shè)計類的原則是,一個類應(yīng)該只有一個用途,它的屬性和服務(wù)應(yīng)該是高內(nèi)聚的。類的屬性和服務(wù)應(yīng)該全都是完成該類對象的任務(wù)所必需的,其中不包含無用的屬性或服務(wù)。如果某個類有多個用途,通常應(yīng)該把它分解成多個專用的類。

3.一般—特殊內(nèi)聚

設(shè)計出的一般—特殊內(nèi)聚應(yīng)該符合多數(shù)人的概念,更準確地說,這種結(jié)構(gòu)應(yīng)該是對相應(yīng)的領(lǐng)域知識的正確抽取。

例如,雖然表面看來飛機與汽車有相似的地方(都用發(fā)動機驅(qū)動,都有輪子……),但是,如果把飛機和汽車都作為“機動車”類的子類,則明顯違背了人們的常識,這樣的一般—特殊內(nèi)聚是低內(nèi)聚的。正確的作法是,設(shè)置一個抽象類“交通工具”,把飛機和機動車作為交通工具類的子類,而汽車又是機動車類的子類。

一般來說,緊密的繼承耦合與高度的一般—特殊內(nèi)聚是一致的。10.1.6可重用

軟件重用是提高軟件開發(fā)生產(chǎn)率和目標系統(tǒng)質(zhì)量的重要途徑。重用基本上從設(shè)計階段開始。重用有兩方面的含義:一是盡量使用已有的類(包括開發(fā)環(huán)境提供的類庫及以往開發(fā)類似系統(tǒng)時創(chuàng)建的類);二是如果確實需要創(chuàng)建新類,則在設(shè)計這些新類的協(xié)議時,應(yīng)該考慮將來的可重復(fù)使用性。 10.2啟發(fā)規(guī)則

10.2.1設(shè)計結(jié)果應(yīng)該清晰易懂

使設(shè)計結(jié)果清晰、易讀、易懂,是提高軟件可維護性和可重用性的重要措施。顯然,人們不會重用那些他們不理解的設(shè)計。保證設(shè)計結(jié)果清晰易懂的主要因素如下:

(1)用詞一致。應(yīng)該使名字與它所代表的事物一致,而且應(yīng)該盡量使用人們習慣的名字。不同類中相似服務(wù)的名字應(yīng)該相同。

(2)使用已有的協(xié)議。如果開發(fā)同一軟件的其他設(shè)計人員已經(jīng)建立了類的協(xié)議,或者在所使用的類庫中已有相應(yīng)的協(xié)議,則應(yīng)該使用這些已有的協(xié)議。

(3)減少消息模式的數(shù)目。如果已有標準的消息協(xié)議,設(shè)計人員應(yīng)該遵守這些協(xié)議。如果確需自己建立消息協(xié)議,則應(yīng)該盡量減少消息模式的數(shù)目。只要可能,就使消息具有一致的模式,以利于讀者理解。

(4)避免模糊的定義。一個類的用途應(yīng)該是有限的,而且應(yīng)該從類名較容易地推想出它的用途。

10.2.2一般—特殊結(jié)構(gòu)的深度應(yīng)適當

應(yīng)該使類等級中包含的層次數(shù)適當。一般來說,在一個中等規(guī)模(大約包含100個類)的系統(tǒng)中,類等級層次數(shù)應(yīng)保持為7±2。不應(yīng)該僅僅從方便編碼的角度出發(fā)隨意創(chuàng)建派生類,應(yīng)該使一般—特殊結(jié)構(gòu)與領(lǐng)域知識或常識保持一致。10.2.3設(shè)計簡單的類

應(yīng)該盡量設(shè)計小而簡單的類,以便于開發(fā)和管理。當類很大的時候,要記住它的所有服務(wù)是非常困難的。經(jīng)驗表明,如果一個類的定義不超過一頁紙(或兩屏),則使用這個類是比較容易的。為使類保持簡單,應(yīng)該注意以下幾點:

(1)避免包含過多的屬性。屬性過多通常表明這個類過分復(fù)雜,它所完成的功能可能太多了。

(2)有明確的定義。為了使類的定義明確,分配給每個類的任務(wù)應(yīng)該簡單,最好能用1~2個簡單語句描述它的任務(wù)。

(3)盡量簡化對象之間的合作關(guān)系。如果需要多個對象協(xié)同配合才能做好一件事,則破壞了類的簡明性和清晰性。

(4)不要提供太多服務(wù)。一個類提供的服務(wù)過多,同樣表明這個類過分復(fù)雜。典型地,一個類提供的公共服務(wù)不超過7個。

在開發(fā)大型軟件系統(tǒng)時,遵循上述啟發(fā)規(guī)則也會帶來另一個問題,即設(shè)計出大量較小的類,這同樣也會帶來一定復(fù)雜性。解決這個問題的辦法是把系統(tǒng)中的類按邏輯分組,也就是劃分“主題”。

10.2.4使用簡單的協(xié)議

一般來說,消息中的參數(shù)不要超過3個。當然,不超過3個的限制也不是絕對的。但是,經(jīng)驗表明,通過復(fù)雜消息相互關(guān)聯(lián)的對象是緊耦合的,對一個對象的修改往往導(dǎo)致其他對象的修改。10.2.5使用簡單的服務(wù)

采用面向?qū)ο蠓椒ㄔO(shè)計出來的類中的服務(wù)通常都很小,一般只有3~5行源程序語句,可以用僅含一個動詞和一個賓語的簡單句子描述它的功能。如果一個服務(wù)中包含了過多的源程序語句,或者語句嵌套層次太多,又或者使用了復(fù)雜的CASE語句,則應(yīng)該仔細檢查這個服務(wù),設(shè)法分解或簡化它。一般來說,應(yīng)該盡量避免使用復(fù)雜的服務(wù)。如果需要在服務(wù)中使用CASE語句,通常應(yīng)該考慮用一般—特殊結(jié)構(gòu)代替這個類的可能性。10.2.6把設(shè)計變動減至最小

通常,設(shè)計的質(zhì)量越高,設(shè)計結(jié)果保持不變的時間也越長。即使出現(xiàn)必須修改設(shè)計的情況,也應(yīng)該使修改的范圍盡可能小。理想的設(shè)計變動曲線如圖10.1所示。

在設(shè)計的早期階段變動較大,隨著時間的推移,設(shè)計方案日趨成熟,改動也就越來越小了。圖10.1中的峰值與出現(xiàn)設(shè)計錯誤或發(fā)生非預(yù)期變動的情況相對應(yīng)。峰值越高,表明設(shè)計質(zhì)量越差,可重用性也越差。圖10.1理想的設(shè)計變動曲線 10.3系統(tǒng)分解

人類解決復(fù)雜問題時普遍采用的策略是“分而治之,各個擊破”。同樣,軟件工程師在設(shè)計比較復(fù)雜的應(yīng)用系統(tǒng)時普遍采用的策略,也是首先把系統(tǒng)分解成若干個比較小的部分,然后再分別設(shè)計每個部分。這樣做有利于降低設(shè)計的難度,有利于分工協(xié)作,也有利于維護人員對系統(tǒng)進行理解和維護。

系統(tǒng)的主要組成部分稱為子系統(tǒng),通常根據(jù)所提供的功能來劃分子系統(tǒng)。例如,編譯系統(tǒng)可劃分成詞法分析、語法分析、中間代碼生成、優(yōu)化、目標代碼生成和出錯處理等子系統(tǒng)。一般來說,子系統(tǒng)的數(shù)目應(yīng)該與系統(tǒng)規(guī)?;酒ヅ洹8鱾€子系統(tǒng)之間應(yīng)該具有盡可能簡單、明確的接口。接口確定了交互形式和通過子系統(tǒng)邊界的信息流,但是無須規(guī)定子系統(tǒng)內(nèi)部的實現(xiàn)算法。因此,可以相對獨立地設(shè)計各個子系統(tǒng)。

在劃分和設(shè)計子系統(tǒng)時,應(yīng)該盡量減少子系統(tǒng)彼此間的依賴性。

采用面向?qū)ο蠓椒ㄔO(shè)計軟件系統(tǒng)時,面向?qū)ο笤O(shè)計模型(即求解域的對象模型)與面向?qū)ο蠓治瞿P?即問題域的對象模型)一樣,也由主題、類與對象、結(jié)構(gòu)、屬性和服務(wù)五個層次組成。這五個層次一層比一層表示的細節(jié)更多,我們可以把這五個層次想象為整個模型的水平切片。此外,大多數(shù)系統(tǒng)的面向?qū)ο笤O(shè)計模型在邏輯上都由四大部分組成。這四大部分對應(yīng)于組成目標系統(tǒng)的四個子系統(tǒng),它們分別是問題域子系統(tǒng)、人機交互子系統(tǒng)、任務(wù)管理子系統(tǒng)和數(shù)據(jù)管理子系統(tǒng)。當然,在不同的軟件系統(tǒng)中,這四個子系統(tǒng)的重要程度和規(guī)模可能相差很大,規(guī)模過大的在設(shè)計過程中應(yīng)該進一步劃分成更小的子系統(tǒng),規(guī)模過小的可合并在其他子系統(tǒng)中。某些領(lǐng)域的應(yīng)用系統(tǒng)在邏輯上可能僅由3個(甚至少于3個)的子系統(tǒng)組成。

我們可以把面向?qū)ο笤O(shè)計模型的四大組成部分想象成整個模型的四個垂直切片。典型的面向?qū)ο笤O(shè)計模型可以用圖10.2表示。圖10.2典型的面向?qū)ο笤O(shè)計模型10.3.1子系統(tǒng)之間的兩種交互方式

在軟件系統(tǒng)中,子系統(tǒng)之間的交互有兩種可能的方式,分別是客戶—供應(yīng)商(Client-supplier)關(guān)系和平等伙伴(peer-to-peer)關(guān)系。

1.客戶—供應(yīng)商關(guān)系

在這種關(guān)系中,作為“客戶”的子系統(tǒng)調(diào)用作為“供應(yīng)商”的子系統(tǒng),后者完成某些服務(wù)工作并返回結(jié)果。使用這種交互方案,作為客戶的子系統(tǒng)必須了解作為供應(yīng)商的子系統(tǒng)的接口,然而后者卻無須了解前者的接口,因為任何交互行為都是由前者驅(qū)動的。

2.平等伙伴關(guān)系

在這種關(guān)系中,每個子系統(tǒng)都可能調(diào)用其他子系統(tǒng),因此,每個子系統(tǒng)都必須了解其他子系統(tǒng)的接口。由于各個子系統(tǒng)需要相互了解對方的接口,因此這種組織系統(tǒng)的方案比起客戶—供應(yīng)商方案來,子系統(tǒng)之間的交互更復(fù)雜,而且這種交互方式還可能存在通信環(huán)路,從而使系統(tǒng)難于理解,容易發(fā)生不易察覺的設(shè)計錯誤。

總的來說,單向交互比雙向交互更容易理解,也更容易設(shè)計和修改,因此應(yīng)該盡量使用客戶—供應(yīng)商關(guān)系。10.3.2組織系統(tǒng)的兩種方案

把子系統(tǒng)組織成完整的系統(tǒng)時,有水平層次組織和垂直塊組織兩種方案可供選擇。

1.層次組織

層次組織方案把軟件系統(tǒng)組織成一個層次系統(tǒng),每層是一個子系統(tǒng),上層在下層的基礎(chǔ)上建立,下層為實現(xiàn)上層功能提供必要的服務(wù)。每一層內(nèi)所包含的對象,彼此間相互獨立;而處于不同層次上的對象,彼此間往往有關(guān)聯(lián)。實際上,在上、下層之間存在客戶—供應(yīng)商關(guān)系。低層子系統(tǒng)提供服務(wù),相當于供應(yīng)商;上層子系統(tǒng)使用下層提供的服務(wù),相當于客戶。層次結(jié)構(gòu)又可進一步劃分成兩種模式:封閉式和開放式。所謂封閉式,就是每層子系統(tǒng)僅僅使用其直接下層提供的服務(wù)。由于一個層次的接口只影響與其緊鄰的上一層,因此,這種工作模式降低了各層次之間的相互依賴性,更容易理解和修改。在開放模式中,某層子系統(tǒng)可以使用處于其下面的任何一層子系統(tǒng)所提供的服務(wù)。這種工作模式的優(yōu)點,是減少了需要在每層重新定義的服務(wù)數(shù)目,使得整個系統(tǒng)更高效、更緊湊。但是,開放模式的系統(tǒng)不符合信息隱藏原則,對任何一個子系統(tǒng)的修改都會影響處在更高層次的那些子系統(tǒng)。設(shè)計軟件系統(tǒng)時到底采用哪種結(jié)構(gòu)模式,需要權(quán)衡效率和模塊獨立性等多種因素,通盤考慮以后再做決定。通常,在需求陳述中只描述了對系統(tǒng)頂層和底層的需求,頂層就是用戶看到的目標系統(tǒng),底層則是可以使用的資源。這兩層往往差異很大,設(shè)計者必須設(shè)計一些中間層次,以減少不同層次之間的概念差異。

2.塊狀組織

塊狀組織方案把軟件系統(tǒng)垂直地分解成若干個相對獨立的、弱耦合的子系統(tǒng),一個子系統(tǒng)相當于一塊,每塊提供一種類型的服務(wù)。

利用層次和塊的各種可能的組合,可以成功地由多個子系統(tǒng)組成一個完整的軟件系統(tǒng)。當混合使用層次結(jié)構(gòu)和塊狀結(jié)構(gòu)時,同一層次可以由若干塊組成,而同一塊也可以分為若干層。例如,圖10.3表示一個應(yīng)用系統(tǒng)的組織結(jié)構(gòu),這個應(yīng)用系統(tǒng)采用了層次與塊狀的混合結(jié)構(gòu)。圖10.3典型應(yīng)用系統(tǒng)的組織結(jié)構(gòu)10.3.3設(shè)計系統(tǒng)的拓撲結(jié)構(gòu)

完整系統(tǒng)的典型的拓撲結(jié)構(gòu)有管道型、樹形、星形等。設(shè)計者應(yīng)該采用與問題結(jié)構(gòu)相適應(yīng)的、盡可能簡單的拓撲結(jié)構(gòu),來減少子系統(tǒng)之間的交互數(shù)量。

10.4設(shè)計問題域子系統(tǒng)

10.4.1調(diào)整需求

有兩種情況會導(dǎo)致修改通過面向?qū)ο蠓治鏊_定的系統(tǒng)需求:一是用戶需求或外部環(huán)境發(fā)生了變化;二是分析員對問題域理解不透徹或缺乏領(lǐng)域?qū)<規(guī)椭?,以致面向?qū)ο蠓治瞿P筒荒芡暾?、準確地反映用戶的真實需求。

無論出現(xiàn)上述哪種情況,通常都只需簡單地修改面向?qū)ο蠓治鼋Y(jié)果,然后再把這些修改反映到問題域子系統(tǒng)中。10.4.2重用已有的類

代碼重用從設(shè)計階段開始,在研究面向?qū)ο蠓治鼋Y(jié)果時就應(yīng)該尋找使用已有類的方法。若因為沒有合適的類可以重用而確實需要創(chuàng)建新的類,則在設(shè)計這些新類的協(xié)議時,必須考慮到將來的可重用性。

如果有可能重用已有的類,則重用已有類的典型過程如下:

●選擇有可能被重用的已有類,標出這些候選類中對本問題無用的屬性和服務(wù),盡量重用那些能使無用的屬性和服務(wù)降到最低程度的類。

●在被重用的已有類和問題域類之間添加歸納關(guān)系(即從被重用的已有類派生出問題域類)?!駱顺鰡栴}域類中從已有類繼承來的屬性和服務(wù),在問題域類內(nèi)不需再定義它們了。

●修改與問題域類相關(guān)的關(guān)聯(lián),必要時將其改為與被重用的已有類相關(guān)的關(guān)聯(lián)。

10.4.3把問題域類組合在一起

在面向?qū)ο笤O(shè)計過程中,設(shè)計者往往通過引入一個根類而把問題域類組合在一起。事實上,這是在沒有更先進的組合機制可用時才采用的一種組合方法。此外,這樣的根類還可以用來建立協(xié)議(見下一小節(jié))。10.4.4增添一般化類以建立協(xié)議

在設(shè)計過程中常常發(fā)現(xiàn),一些具體類需要有一個公共的協(xié)議。也就是說,它們都需要定義一組類似的服務(wù)(很可能還需要相應(yīng)的屬性)。在這種情況下可以引入一個附加類(例如根類),以便建立這個協(xié)議(即命名公共服務(wù)集合,這些服務(wù)在具體類中仔細定義)。10.4.5ATM系統(tǒng)之例

圖10.4描繪了第9章給出的ATM系統(tǒng)的問題域子系統(tǒng)的結(jié)構(gòu)。在面向?qū)ο笤O(shè)計過程中,我們把ATM系統(tǒng)的問題域子系統(tǒng)進一步劃分成了三個更小的子系統(tǒng),它們分別是ATM站子系統(tǒng)、中央計算機子系統(tǒng)和分行計算機子系統(tǒng)。它們的拓撲結(jié)構(gòu)為星形,即以中央計算機為中心向外輻射,同所有ATM站及分行計算機通信。物理連接用專用電話線實現(xiàn)。根據(jù)ATM站號和分行代碼,區(qū)分由每個ATM站和每臺分行計算機連向中央計算機的電話線。圖10.4ATM系統(tǒng)問題域子系統(tǒng)的結(jié)構(gòu) 10.5設(shè)計人機交互子系統(tǒng)

10.5.1設(shè)計人機交互界面的準則

遵循下列準則有助于設(shè)計出讓用戶滿意的人機交互界面:

(1)一致性。使用一致的術(shù)語、一致的步驟和一致的動作。

(2)減少步驟。應(yīng)使用戶為做某件事情而需敲擊鍵盤的次數(shù)、點按鼠標的次數(shù)或者下拉菜單的距離都減至最少,還應(yīng)使得技術(shù)水平不同的用戶,為獲得有意義的結(jié)果所需使用的時間都減至最少。特別應(yīng)該為熟練用戶提供簡捷的操作方法(例如熱鍵)。

(3)及時提供反饋信息。每當用戶等待系統(tǒng)完成一項工作時,系統(tǒng)都應(yīng)該向用戶提供有意義的、及時的反饋信息,以便用戶能夠知道系統(tǒng)目前已經(jīng)完成該項工作的多大比例。

(4)提供撤消命令。人在與系統(tǒng)交互的過程中難免會犯錯誤,因此,應(yīng)該提供“撤消(undo)”命令,以便用戶及時撤消錯誤動作,消除錯誤動作造成的后果。

(5)無須記憶。不應(yīng)該要求用戶記住在某個窗口中顯示的信息,然后再用到另一個窗口中,這是軟件系統(tǒng)的責任而不是用戶的任務(wù)。

此外,在設(shè)計人機交互部分時應(yīng)該力求達到下述目標:用戶在使用該系統(tǒng)時用于思考人機交互方法所花費的時間減至最少,而用于做其他實際想做的工作所用的時間達到最大值。更理想的情況是,人機交互界面能夠增強用戶的能力。

(6)易學。人機交互界面應(yīng)該易學易用,應(yīng)該提供聯(lián)機參考資料,以便用戶在遇到困難時隨時參閱。

(7)富有吸引力。人機交互界面不僅應(yīng)該方便、高效,還應(yīng)該使人在使用時感到心情愉快,能夠從中獲得樂趣,從而吸引人去使用它。

10.5.2設(shè)計人機交互子系統(tǒng)的策略

1.分類用戶

人機交互界面是給用戶使用的。顯然,為設(shè)計好人機交互子系統(tǒng),設(shè)計者應(yīng)該認真研究使用它的用戶。應(yīng)該深入到用戶的工作現(xiàn)場,仔細觀察用戶是怎樣做他們的工作的,這對設(shè)計好人機交互界面非常必要。在深入現(xiàn)場的過程中,設(shè)計者應(yīng)該認真思考下述問題:用戶必須完成哪些工作?設(shè)計者能夠提供什么工具來支持這些工作的完成?怎樣使得這些工具使用起來更方便、更有效?

為了更好地了解用戶的需要與愛好,以便設(shè)計出符合用戶需要的界面,設(shè)計者首先應(yīng)該把將來可能與系統(tǒng)交互的用戶分類。通常從下列幾個不同角度進行分類:

①按技能水平分類(新手/初級/中級/高級)。

②按職務(wù)分類(總經(jīng)理/經(jīng)理/職員)。

③按所屬集團分類(職員/顧客)。

2.描述用戶

應(yīng)該仔細了解將來使用系統(tǒng)的每類用戶的情況,把獲得的下列各項信息記錄下來。

①用戶類型。

②使用系統(tǒng)欲達到的目的。

③特征(年齡、性別、受教育程度、使用系統(tǒng)的權(quán)限等)。

④關(guān)鍵的成功因素(需求、愛好、習慣等)。

⑤技能水平。

⑥完成本職工作的腳本。

3.設(shè)計命令層次

設(shè)計命令層次的工作通常包含以下幾項內(nèi)容:

(1)研究現(xiàn)有的人機交互含義和準則?,F(xiàn)在,Windows已經(jīng)成了微機上圖形用戶界面事實上的工業(yè)標準。所有Windows應(yīng)用程序的基本外觀及給用戶的感受都是相同的(例如,每個程序至少有一個窗口,它由標題欄標識;程序中大多數(shù)功能可通過菜單選用;選中某些菜單項會彈出對話框,用戶可通過它輸入附加信息……)。Windows程序通常還遵守廣大用戶習以為常的許多約定(例如,F(xiàn)ile菜單的最后一個菜單項是Exit;在文件列表框中用鼠標單擊某個表項,則相應(yīng)的文件名變亮,若用鼠標雙擊則會打開該文件……)。設(shè)計圖形用戶界面時,應(yīng)該保持與普通Windows應(yīng)用程序界面相一致,并遵守廣大用戶習慣的約定,這樣才會被用戶接受和喜受。

(2)確定初始的命令層次。所謂命令層次,實質(zhì)上是用過程抽象機制組織起來的、可供選用的服務(wù)的表示形式。設(shè)計命令層次時,通常先從對服務(wù)的過程抽象著手,然后再進一步修改它們,以適合具體應(yīng)用環(huán)境的需要。

(3)精化命令層次。為進一步修改完善初始的命令層次,應(yīng)該考慮下列一些因素:

①次序:仔細選擇每個服務(wù)的名字,并在命令層的每一部分內(nèi)把服務(wù)排好次序。排序時或者把最常用的服務(wù)放在最前面,或者按照用戶習慣的工作步驟排序。②整體—部分關(guān)系:尋找在這些服務(wù)中存在的整體—部分模式,這樣做有助于在命令層中分組組織服務(wù)。

③寬度和深度:由于人的短期記憶能力有限,命令層次的寬度和深度都不應(yīng)該過大。

④操作步驟:應(yīng)該用盡量少的單擊、拖動和擊鍵組合來表達命令,而且應(yīng)該為高級用戶提供簡捷的操作方法。

4.設(shè)計人機交互類

人機交互類與所使用的操作系統(tǒng)及編程語言密切相關(guān)。例如,在Windows環(huán)境下運行的VisualC++語言提供了MFC類庫。設(shè)計人機交互類時,往往僅需從MFC類庫中選出一些適用的類,然后從這些類派生出符合自己需要的類即可。 10.6設(shè)計任務(wù)管理子系統(tǒng)

10.6.1分析并發(fā)性

通過面向?qū)ο蠓治鼋⑵饋淼膭討B(tài)模型,是分析并發(fā)性的主要依據(jù)。如果兩個對象彼此間不存在交互,或者它們同時接受事件,則這兩個對象在本質(zhì)上是并發(fā)的。通過檢查各個對象的狀態(tài)圖及它們之間交換的事件,能夠把若干個非并發(fā)的對象歸并到一條控制線中。所謂控制線,是一條遍及狀態(tài)圖集合的路徑,在這條路徑上每次只有一個對象是活動的。在計算機系統(tǒng)中用任務(wù)(task)實現(xiàn)控制線,一般認為任務(wù)是進程(process)的別名。通常把多個任務(wù)的并發(fā)執(zhí)行稱為多任務(wù)。對于某些應(yīng)用系統(tǒng)來說,通過劃分任務(wù),可以簡化系統(tǒng)的設(shè)計及編碼工作。不同的任務(wù)標識了必須同時發(fā)生的不同行為,這種并發(fā)行為既可以在不同的處理器上實現(xiàn),也可以在單個處理器上利用多任務(wù)操作系統(tǒng)仿真實現(xiàn)(通常采用時間分片策略仿真多處理器環(huán)境)。

10.6.2設(shè)計任務(wù)管理子系統(tǒng)

常見的任務(wù)有事件驅(qū)動型任務(wù)、時鐘驅(qū)動型任務(wù)、優(yōu)先任務(wù)、關(guān)鍵任務(wù)和協(xié)調(diào)任務(wù)等。設(shè)計任務(wù)管理子系統(tǒng)包括確定各類任務(wù)并把任務(wù)分配給適當?shù)挠布蜍浖?zhí)行。

1.確定事件驅(qū)動型任務(wù)

某些任務(wù)是由事件驅(qū)動的,這類任務(wù)可能主要完成通信工作,例如與設(shè)備、屏幕窗口、其他任務(wù)、子系統(tǒng)、另一個處理器或其他系統(tǒng)通信。事件通常是表明某些數(shù)據(jù)到達的信號。

在系統(tǒng)運行時,這類任務(wù)的工作過程如下:任務(wù)處于睡眠狀態(tài)(不消耗處理器時間),等待來自數(shù)據(jù)線或其他數(shù)據(jù)源的中斷;一旦接收到中斷就喚醒了該任務(wù),接收數(shù)據(jù)并把數(shù)據(jù)放入內(nèi)存緩沖區(qū)或其他目的地,通知需要知道這件事的對象,然后該任務(wù)又回到睡眠狀態(tài)。

2.確定時鐘驅(qū)動型任務(wù)

某些任務(wù)每隔一定時間間隔就被觸發(fā)以執(zhí)行某些處理。例如,某些設(shè)備需要周期性地獲得數(shù)據(jù);某些人機接口、子系統(tǒng)、任務(wù)、處理器或其他系統(tǒng)也可能需要周期性的通信。在這些場合往往需要使用時鐘驅(qū)動型任務(wù)。

時鐘驅(qū)動型任務(wù)的工作過程如下:任務(wù)設(shè)置了喚醒時間后進入睡眠狀態(tài);任務(wù)睡眠(不消耗處理器時間),等待來自系統(tǒng)的中斷;一旦接收到這種中斷,任務(wù)就被喚醒并做它的工作,通知有關(guān)的對象,然后該任務(wù)又回到睡眠狀態(tài)。

3.確定優(yōu)先任務(wù)

優(yōu)先任務(wù)可以滿足高優(yōu)先級或低優(yōu)先級的處理需求。

●高優(yōu)先級。某些服務(wù)具有很高的優(yōu)先級,為了在嚴格限定的時間內(nèi)完成這種服務(wù),可能需要把這類服務(wù)分離成獨立的任務(wù)。

●低優(yōu)先級。與高優(yōu)先級相反,有些服務(wù)是低優(yōu)先級的,屬于低優(yōu)先級處理(通常指那些背景處理)。設(shè)計時可能用額外的任務(wù)把這樣的處理分離出來。

4.確定關(guān)鍵任務(wù)

關(guān)鍵任務(wù)是有關(guān)系統(tǒng)成功或失敗的關(guān)鍵處理,這類處理通常都有嚴格的可靠性要求。在設(shè)計過程中可能用額外的任務(wù)把這樣的關(guān)鍵處理分離出來,以滿足高可靠性處理的要求。對高可靠性處理應(yīng)該精心設(shè)計和編碼,并且應(yīng)該嚴格測試。

5.確定協(xié)調(diào)任務(wù)

當系統(tǒng)中存在三個以上任務(wù)時,就應(yīng)該增加一個任務(wù),用它作為協(xié)調(diào)任務(wù)。引入?yún)f(xié)調(diào)任務(wù)會增加系統(tǒng)的總開銷(增加從一個任務(wù)到另一個任務(wù)的轉(zhuǎn)換時間),但是引入?yún)f(xié)調(diào)任務(wù)有助于把不同任務(wù)之間的協(xié)調(diào)控制封裝起來。使用狀態(tài)轉(zhuǎn)換矩陣可以比較方便地描述該類任務(wù)的行為。這類任務(wù)應(yīng)該僅做協(xié)調(diào)工作,不要讓它再承擔其他服務(wù)工作。

6.盡量減少任務(wù)數(shù)

必須仔細分析和選擇每個確實需要的任務(wù)。應(yīng)該使系統(tǒng)中包含的任務(wù)數(shù)盡量少。設(shè)計多任務(wù)系統(tǒng)的主要問題是,設(shè)計者常常為了自己處理時的方便而輕率地定義過多的任務(wù)。這樣做加大了設(shè)計工作的技術(shù)復(fù)雜度,并使系統(tǒng)變得不易理解,從而也加大了系統(tǒng)維護的難度。

7.確定資源需求

使用多處理器或固件主要是為了滿足高性能的需求。設(shè)計者必須通過計算系統(tǒng)載荷(即每秒處理的業(yè)務(wù)數(shù)及處理一個業(yè)務(wù)所花費的時間),來估算所需要的CPU(或其他固件)的處理能力。設(shè)計者應(yīng)該綜合考慮各種因素,以決定哪些子系統(tǒng)用硬件實現(xiàn),哪些子系統(tǒng)用軟件實現(xiàn)。下述兩個因素可能是使用硬件實現(xiàn)某些子系統(tǒng)的主要原因:

●現(xiàn)有的硬件完全能滿足某些方面的需求。例如,買一塊浮點運算卡比用軟件實現(xiàn)浮點運算要容易得多。

●專用硬件比通用的CPU性能更高。例如,目前在信號處理系統(tǒng)中廣泛使用固件實現(xiàn)快速付里葉變換。

設(shè)計者在決定到底采用軟件還是硬件的時候,必須綜合權(quán)衡一致性、成本和性能等多種因素,還要考慮未來的可擴充性和可修改性。 10.7設(shè)計數(shù)據(jù)管理子系統(tǒng)

10.7.1選擇數(shù)據(jù)存儲管理模式

1.文件管理系統(tǒng)

文件管理系統(tǒng)是操作系統(tǒng)的一個組成部分,使用它長期保存數(shù)據(jù)具有成本低和簡單等特點。但是,文件操作的級別低,為提供適當?shù)某橄蠹墑e還必須編寫額外的代碼。此外,不同操作系統(tǒng)的文件管理系統(tǒng)往往有明顯差異。

2.關(guān)系數(shù)據(jù)庫管理系統(tǒng)

關(guān)系數(shù)據(jù)庫管理系統(tǒng)的理論基礎(chǔ)是關(guān)系代數(shù),它不僅理論基礎(chǔ)堅實而且有下列一些主要優(yōu)點:

①提供了各種最基本的數(shù)據(jù)管理功能,例如中斷恢復(fù)、多用戶共享、多應(yīng)用共享、完整性和事務(wù)支持等。②為多種應(yīng)用提供了一致的接口。

③標準化的語言(大多數(shù)商品化關(guān)系數(shù)據(jù)庫管理系統(tǒng)都使用SQL語言)。

但是,為了做到通用與一致,關(guān)系數(shù)據(jù)庫管理系統(tǒng)通常都相當復(fù)雜,且有下述一些具體缺點,以致限制了這種系統(tǒng)的普遍使用。

①運行開銷大,即使只完成簡單的事務(wù)(例如只修改表中的一行),也需要較長的時間。

②不能滿足高級應(yīng)用的需求。關(guān)系數(shù)據(jù)庫管理系統(tǒng)是為商務(wù)應(yīng)用服務(wù)的,商務(wù)應(yīng)用中數(shù)據(jù)量雖大但數(shù)據(jù)結(jié)構(gòu)卻比較簡單。事實上,關(guān)系數(shù)據(jù)庫管理系統(tǒng)很難用在數(shù)據(jù)類型豐富或操作不標準的應(yīng)用中。③與程序設(shè)計語言的連接不自然。SQL語言支持面向集合的操作,是一種非過程性語言。然而大多數(shù)程序設(shè)計語言本質(zhì)上卻是過程性的,每次只能處理一個記錄。

3.面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)

面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)是一種新技術(shù),主要有兩種設(shè)計途徑:擴展的關(guān)系數(shù)據(jù)庫管理系統(tǒng)和擴展的面向?qū)ο蟪绦蛟O(shè)計語言。

①擴展的關(guān)系數(shù)據(jù)庫管理系統(tǒng)是在關(guān)系數(shù)據(jù)庫的基礎(chǔ)上,增加了抽象數(shù)據(jù)類型和繼承機制,此外還增加了創(chuàng)建及管理類和對象的通用服務(wù)。②擴展的面向?qū)ο蟪绦蛟O(shè)計語言擴充了面向?qū)ο蟪绦蛟O(shè)計語言的語法和功能,增加了在數(shù)據(jù)庫中存儲和管理對象的機制。開發(fā)人員可以用統(tǒng)一的面向?qū)ο笥^點進行設(shè)計,不再需要區(qū)分存儲數(shù)據(jù)結(jié)構(gòu)和程序數(shù)據(jù)結(jié)構(gòu)(即生命期短暫的數(shù)據(jù))。

目前,大多數(shù)“對象”數(shù)據(jù)管理模式都采用“復(fù)制對象”的方法:先保留對象值,然后在需要時創(chuàng)建該對象的一個副本。擴展的面向?qū)ο蟪绦蛟O(shè)計語言則擴充了這種機制,它支持“永久對象”方法:準確存儲對象(包括對象的內(nèi)部標識在內(nèi)),而不是僅僅存儲對象值。使用這種方法,當從存儲器中檢索出一個對象的時候,它就完全等同于原先存在的那個對象?!坝谰脤ο蟆狈椒樵诙嘤脩舡h(huán)境下從對象服務(wù)器中共享對象奠定了基礎(chǔ)。10.7.2設(shè)計數(shù)據(jù)管理子系統(tǒng)

1.設(shè)計數(shù)據(jù)格式

設(shè)計數(shù)據(jù)格式的方法與所使用的數(shù)據(jù)存儲管理模式密切相關(guān)。下面分別介紹適用于每種數(shù)據(jù)存儲管理模式的設(shè)計方法。

(1)文件系統(tǒng)。具體步驟是:

①定義第一范式表:列出每個類的屬性表;把屬性表規(guī)范成第一范式,從而得到第一范式表的定義。

②為每個第一范式表定義一個文件。

③測量性能和需要的存儲容量。

④修改原設(shè)計的第一范式,以滿足性能和存儲需求。必要時把歸納結(jié)構(gòu)的屬性壓縮在單個文件中,以減少文件數(shù)量,同時把某些屬性組合在一起,并用某種編碼值表示這些屬性,而不再分別使用獨立的域表示每個屬性。這樣做可以減少所需要的存儲空間,但是增加了處理時間。

(2)關(guān)系數(shù)據(jù)庫管理系統(tǒng)。具體步驟是:

①定義第三范式表:列出每個類的屬性表;把屬性表規(guī)范成第三范式,從而得出第三范式表的定義。

②為每個第三范式表定義一個數(shù)據(jù)庫表。

③測量性能和需要的存儲容量。

④修改先前設(shè)計的第三范式,以滿足性能和存儲需求。

(3)面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)。具體步驟是:

①擴展的關(guān)系數(shù)據(jù)庫途徑:使用與關(guān)系數(shù)據(jù)庫管理系統(tǒng)相同的方法。

②擴展的面向?qū)ο蟪绦蛟O(shè)計語言途徑:不需要規(guī)范化屬性的步驟,因為數(shù)據(jù)庫管理系統(tǒng)本身具有把對象值映射成存儲值的功能。

2.設(shè)計相應(yīng)的服務(wù)

如果某個類的對象需要存儲起來,則應(yīng)在這個類中增加一個屬性和服務(wù),用于完成存儲對象自身的工作。應(yīng)該把為此目的增加的屬性和服務(wù)作為“隱含”的屬性和服務(wù),即無需在面向?qū)ο笤O(shè)計模型的屬性和服務(wù)層中顯式地表示它們,僅需在關(guān)于類與對象的文檔中描述它們。這樣設(shè)計之后,對象將知道怎樣存儲自己。用于“存儲自己”的屬性和服務(wù),在問題域子系統(tǒng)和數(shù)據(jù)管理子系統(tǒng)之間構(gòu)成一座必要的橋梁。利用多重繼承機制,可以在某個適當?shù)幕愔卸x這樣的屬性和服務(wù),如果以后某個類的對象需要長期存儲,該類就從基類中繼承這樣的屬性和服務(wù)。

下面介紹使用不同數(shù)據(jù)存儲管理模式時的設(shè)計要點。

(1)文件系統(tǒng)。被存儲的對象需要知道打開哪個(些)文件,怎樣把文件定位到正確的記錄上,怎樣檢索出舊值(如果有的話),以及怎樣用現(xiàn)有值更新它們。

此外,還應(yīng)該定義一個ObjectServer(對象服務(wù)器)類,并創(chuàng)建它的實例。該類提供下列服務(wù):●通知對象保存自身;

●檢索已存儲的對象(查找、讀值、創(chuàng)建并初始化對象),以便把這些對象提供給其他子系統(tǒng)使用。

注意,為提高性能應(yīng)該批量處理訪問文件的要求。

(2)關(guān)系數(shù)據(jù)庫管理系統(tǒng)。被存儲的對象應(yīng)該知道訪問哪些數(shù)據(jù)庫表,怎樣訪問所需要的行,怎樣檢索出舊值(如果有的話),以及怎樣用現(xiàn)有值更新它們。

此外,還應(yīng)該定義一個ObjectServer類,并聲明它的對象。該類提供下列服務(wù):

●通知對象保存自身;

●檢索已存儲的對象(查找、讀值、創(chuàng)建并初始化對象),以便由其他子系統(tǒng)使用這些對象。

(3)面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)。

●擴展的關(guān)系數(shù)據(jù)庫途徑:與使用關(guān)系數(shù)據(jù)庫管理系統(tǒng)時方法相同。

●擴展的面向?qū)ο蟪绦蛟O(shè)計語言途徑:無需增加服務(wù),這種數(shù)據(jù)庫管理系統(tǒng)已經(jīng)給每個對象提供了“存儲自己”的行為。只需給需要長期保存的對象加個標記,然后由面向?qū)ο髷?shù)據(jù)庫管理系統(tǒng)負責存儲和恢復(fù)這類對象。10.7.3例子

為具體說明數(shù)據(jù)管理子系統(tǒng)的設(shè)計方法,讓我們再看看圖10.4所示的ATM系統(tǒng)。

從圖10.4中可以看出,唯一的永久性數(shù)據(jù)存儲在分行計算機中。由于必須保持數(shù)據(jù)的一致性和完整性,而且常常有多個并發(fā)事務(wù)同時訪問這些數(shù)據(jù),因此,采用成熟的商品化關(guān)系數(shù)據(jù)庫管理系統(tǒng)存儲數(shù)據(jù)。應(yīng)該把每個事務(wù)作為一個不可分割的批操作來處理,由事務(wù)封鎖賬戶直到該事務(wù)結(jié)束為止。

在這個例子中,需要存儲的對象主要是賬戶類的對象。為了支持數(shù)據(jù)管理子系統(tǒng)的實現(xiàn),賬戶類對象必須知道自己是怎樣存儲的,有兩種方法可以達到這個目的。

(1)每個對象自己保存自己。賬戶類對象在接到“存儲自己”的通知后,知道怎樣把自身存儲起來(需要增加一個屬性和一個服務(wù)來定義上述行為)。

(2)由數(shù)據(jù)管理子系統(tǒng)負責存儲對象。賬戶類對象在接到“存儲自己”的通知后,知道應(yīng)該向數(shù)據(jù)管理子系統(tǒng)發(fā)送什么消息,以便由數(shù)據(jù)管理子系統(tǒng)把它的狀態(tài)保存起來,為此也需要增加屬性和服務(wù)來定義上述行為。使用這種方法的優(yōu)點是無需修改問題域子系統(tǒng)。

如上一小節(jié)所述,應(yīng)該定義一個數(shù)據(jù)管理類ObjectServer并聲明它的對象。這個類提供下列服務(wù):

●通知對象保存自身或保存需長期存儲的對象的狀態(tài);

●檢索已存儲的對象并使之“復(fù)活”。

10.8設(shè)計類中的服務(wù)

10.8.1確定類中應(yīng)有的服務(wù)

需要綜合考慮對象模型、動態(tài)模型和功能模型,才能正確確定類中應(yīng)有的服務(wù)。對象模型是進行對象設(shè)計的基本框架。但是,面向?qū)ο蠓治龅贸龅膶ο竽P?,通常只在每個類中列出很少幾個最核心的服務(wù)。設(shè)計者必須把動態(tài)模型中對象的行為以及功能模型中的數(shù)據(jù)處理轉(zhuǎn)換成由適當?shù)念愃峁┑姆?wù)。

一張狀態(tài)圖描繪了一個對象的生命周期,圖中的狀態(tài)轉(zhuǎn)換是執(zhí)行對象服務(wù)的結(jié)果。對象的許多服務(wù)都與對象接受的事件密切相關(guān)。事實上,事件就表現(xiàn)為消息,接受消息的對象必然有由消息選擇符指定的服務(wù),該服務(wù)改變對象狀態(tài)(修改相應(yīng)的屬性值)并完成對象應(yīng)做的動作。對象的動作既與事件有關(guān),也與對象的狀態(tài)有關(guān)。因此,完成服務(wù)的算法自然也和對象的狀態(tài)有關(guān)。如果一個對象在不同狀態(tài)可以接受同樣事件,而且在不同狀態(tài)接受到同樣事件時其行為不同,則實現(xiàn)服務(wù)的算法中需要有一個依賴于狀態(tài)的DO_CASE型控制結(jié)構(gòu)。

功能模型指明了系統(tǒng)必須提供的服務(wù)。狀態(tài)圖中狀態(tài)轉(zhuǎn)換所觸發(fā)的動作,在功能模型中有時可能擴展成一張數(shù)據(jù)流圖。數(shù)據(jù)流圖中的某些處理可能與對象提供的服務(wù)相對應(yīng)。下列規(guī)則有助于確定操作的目標對象(即應(yīng)該在該對象所屬的類中定義這個服務(wù))?!袢绻硞€處理的功能是從輸入流中抽取一個值,則該輸入流就是目標對象。

●如果某個處理具有類型相同的輸入流和輸出流,而且輸出流實質(zhì)上是輸入流的另一種形式,則該輸入/輸出流就是目標對象。

●如果某個處理從多個輸入流得出輸出值,則該處理是輸出類中定義的一個服務(wù)。

●如果某個處理把對輸入流處理的結(jié)果輸出給數(shù)據(jù)存儲或動作對象,則該數(shù)據(jù)存儲或動作對象就是目標對象。

當一個處理涉及多個對象時,為確定把它作為哪個對象的服務(wù),設(shè)計者必須判斷哪個對象在這個處理中起主要作用。通常在起主要作用的對象類中定義這個服務(wù)。下面兩條規(guī)則有助于確定處理的歸屬?!袢绻幚碛绊懟蛐薷牧艘粋€對象,則最好把該處理與處理的目標(而不是觸發(fā)者)聯(lián)系在一起。

●考察處理涉及的對象類及這些類之間的關(guān)聯(lián),從中找出處于中心地位的類。如果其他類和關(guān)聯(lián)圍繞這個中心類構(gòu)成星形結(jié)構(gòu),則這個中心類就是處理的目標。10.8.2設(shè)計實現(xiàn)服務(wù)的方法

在面向?qū)ο笤O(shè)計過程中還應(yīng)該進一步設(shè)計實現(xiàn)服務(wù)的方法,主要應(yīng)該完成以下幾項工作。

1.設(shè)計實現(xiàn)服務(wù)的算法

設(shè)計實現(xiàn)服務(wù)的算法時應(yīng)該考慮下列幾個因素:

(1)算法復(fù)雜度。通常選用復(fù)雜度較低(即效率較高)的算法,但也不要過分追求高效率,應(yīng)以能滿足用戶需求為準。

(2)容易理解與容易實現(xiàn)。容易理解與容易實現(xiàn)的要求往往與高效率有矛盾,設(shè)計者應(yīng)該對這兩個因素適當折中。

(3)易修改。應(yīng)該盡可能預(yù)測將來可能做的修改,并在設(shè)計時預(yù)先做些準備。

2.選擇數(shù)據(jù)結(jié)構(gòu)

在分析階段,僅需考慮系統(tǒng)中需要的信息的邏輯結(jié)構(gòu);而在面向?qū)ο笤O(shè)計過程中,則需要選擇能夠方便、有效地實現(xiàn)算法的物理數(shù)據(jù)結(jié)構(gòu)。

3.定義內(nèi)部類和內(nèi)部操作

在面向?qū)ο笤O(shè)計過程中,可能需要增添一些在需求陳述中沒有提到的類,這些新增加的類主要用來存放在執(zhí)行算法過程中所得出的某些中間結(jié)果。

此外,復(fù)雜操作往往可以用簡單對象上的更低層操作來定義。因此,在分解高層操作時常常引入新的低層操作。在面向?qū)ο笤O(shè)計過程中應(yīng)該定義這些新增加的低層操作。 10.9設(shè)計關(guān)聯(lián)

10.9.1關(guān)聯(lián)的遍歷

在應(yīng)用系統(tǒng)中,使用關(guān)聯(lián)有兩種可能的方式:單向遍歷和雙向遍歷。其中,某些關(guān)聯(lián)只需要單向遍歷,這種單向關(guān)聯(lián)實現(xiàn)起來比較簡單;另外一些關(guān)聯(lián)可能需要雙向遍歷,雙向關(guān)聯(lián)實現(xiàn)起來稍微麻煩一些。

在使用原型法開發(fā)軟件的時候,原型中所有的關(guān)聯(lián)都應(yīng)該是雙向的,以便于增加新的行為,快速地擴充和修改原型。10.9.2實現(xiàn)單向關(guān)聯(lián)

用指針可以方便地實現(xiàn)單向關(guān)聯(lián)。如果關(guān)聯(lián)的重數(shù)是一元的(如圖10.5所示),則實現(xiàn)關(guān)聯(lián)的指針是一個簡單指針;如果重數(shù)是多元的,則需要用一個指針集合實現(xiàn)關(guān)聯(lián)(參見圖10.6)。圖10.5用指針實現(xiàn)單向關(guān)聯(lián)(a)關(guān)聯(lián);(b)實現(xiàn)圖10.6用指針實現(xiàn)雙向關(guān)聯(lián)(a)關(guān)聯(lián);(b)實現(xiàn)10.9.3實現(xiàn)雙向關(guān)聯(lián)

許多關(guān)聯(lián)都需要雙向遍歷,當然,兩個方向遍歷的頻度往往并不相同。實現(xiàn)雙向關(guān)聯(lián)有下列三種方法:

(1)只用屬性實現(xiàn)一個方向的關(guān)聯(lián),當需要反向遍歷時就執(zhí)行一次正向查找。如果兩個方向遍歷的頻度相差很大,而且需要盡量減少存儲開銷和修改時的開銷,則這是一種很有效的實現(xiàn)雙向關(guān)聯(lián)的方法。

(2)兩個方向的關(guān)聯(lián)都用屬性實現(xiàn)。具體實現(xiàn)方法已在上一小節(jié)講過,如圖10.6所示。這種方法能實現(xiàn)快速訪問,但是,如果修改了一個屬性,則相關(guān)的屬性也必須隨之修改,才能保持該關(guān)聯(lián)鏈的一致性。當訪問次數(shù)遠遠多于修改次數(shù)時,這種實現(xiàn)方法很有效。

(3)用獨立的關(guān)聯(lián)對象實現(xiàn)雙向關(guān)聯(lián)。關(guān)聯(lián)對象不屬于相互關(guān)聯(lián)的任何一個類,它是獨立的關(guān)聯(lián)類的實例,如圖10.7所示。圖10.7用對象實現(xiàn)關(guān)聯(lián)10.9.4關(guān)聯(lián)對象的實現(xiàn)方法

前文曾經(jīng)講過,可以引入一個關(guān)聯(lián)類來保存描述關(guān)聯(lián)性質(zhì)的信息,關(guān)聯(lián)中的每個連接對應(yīng)著關(guān)聯(lián)類的一個對象。實現(xiàn)關(guān)聯(lián)對象的方法取決于關(guān)聯(lián)的重數(shù)。對于一對一關(guān)聯(lián)來說,關(guān)聯(lián)對象可以與參與關(guān)聯(lián)的任一個對象合并。對于一對多關(guān)聯(lián)來說,關(guān)聯(lián)對象可以與“多”端對象合并。如果是多對多關(guān)聯(lián),則關(guān)聯(lián)鏈的性質(zhì)不可能只與一個參與關(guān)聯(lián)的對象有關(guān),通常用一個獨立的關(guān)聯(lián)類來保存描述關(guān)聯(lián)性質(zhì)的信息,這個類的每個實例表示一條具體的關(guān)聯(lián)鏈及該鏈的屬性(參見圖10.7)。 10.10設(shè)計優(yōu)化

10.10.1確定優(yōu)先級

系統(tǒng)的各項質(zhì)量指標并不是同等重要的,設(shè)計人員必須確定各項質(zhì)量指標的相對重要性(即確定優(yōu)先級),以便在優(yōu)化設(shè)計時制定折中方案。

系統(tǒng)的整體質(zhì)量與設(shè)計人員所制定的折中方案密切相關(guān)。最終產(chǎn)品成功與否,在很大程度上取決于是否選擇好了系統(tǒng)目標。最糟糕的情況是,沒有站在全局高度正確確定各項質(zhì)量指標的優(yōu)先級,以致系統(tǒng)中各個子系統(tǒng)按照相互對立的目標做了優(yōu)化,導(dǎo)致系統(tǒng)資源的嚴重浪費。在折中方案中設(shè)置的優(yōu)先級應(yīng)該是模糊的。事實上,不可能指定精確的優(yōu)先級數(shù)值(例如速度48%,內(nèi)存25%,費用8%,可修改性19%)。

最常見的情況是,在效率和清晰性之間尋求適當?shù)恼壑蟹桨?。下面兩小?jié)分別講述在優(yōu)化設(shè)計時提高效率的技術(shù),以及建立良好的繼承結(jié)構(gòu)的方法。10.10.2提高效率的幾項技術(shù)

1.增加冗余關(guān)聯(lián)以提高訪問效率

在面向?qū)ο蠓治鲞^程中,應(yīng)該避免在對象模型中存在的冗余關(guān)聯(lián),因為冗余關(guān)聯(lián)不僅沒有增添關(guān)于問題域的任何信息,反而會降低模型的清晰程度。但是,在面向?qū)ο笤O(shè)計過程中,當考慮用戶的訪問模式及不同類型訪問之間彼此的依賴關(guān)系時,就會發(fā)現(xiàn),分析階段確定的關(guān)聯(lián)可能并沒有構(gòu)成效率最高的訪問路徑。下面用設(shè)計公司雇員技能數(shù)據(jù)庫的例子來說明分析訪問路徑及提高訪問效率的方法。

圖10.8是從面向?qū)ο蠓治瞿P椭刑崛〕龅囊徊糠帧9绢愔械姆?wù)find_skill返回具有指定技能的雇員集合。例如,用戶可能詢問公司內(nèi)會講日語的雇員有哪些人。圖10.8公司、雇員及技能之間的關(guān)聯(lián)鏈假設(shè)某公司共有2000名雇員,平均每名雇員會10種技能,則簡單的嵌套查詢將遍歷雇員對象2000次,針對每名雇員平均再遍歷技能對象10次。如果全公司僅有5名雇員精通日語,則查詢命中率僅有1/4000。

提高訪問效率的一種方法是使用哈希(Hash)表。“具有技能”這個關(guān)聯(lián)不再利用無序表實現(xiàn),而是改用哈希表實現(xiàn)。只要“會講日語”是用唯一一個技能對象表示,那么改進后就會使查詢次數(shù)由20?000次減少到2000次。但是,當只有極少數(shù)對象滿足查詢條件時,查詢命中率仍然很低。這時,提高查詢效率更有效的方法是給那些需要經(jīng)常查詢的對象建立索引。例如,針對上述例子,我們可以增加一個額外的限定關(guān)聯(lián)“精通語言”,用來聯(lián)系公司與雇員這兩類對象,如圖10.9所示。利用適當?shù)娜哂嚓P(guān)聯(lián),可以立即查到精通某種具體語言的雇員,而無須多余的訪問。當然,索引也必然帶來開銷:占用內(nèi)存空間,而且每當修改基關(guān)聯(lián)時也必須相應(yīng)地修改索引。因此,應(yīng)該只給那些經(jīng)常執(zhí)行并且開銷大、命中率低的查詢建立索引。圖10.9為雇員技能數(shù)據(jù)庫建立索引

2.調(diào)整查詢次序

改進了對象模型的結(jié)構(gòu),從而優(yōu)化了常用的遍歷之后,接下來就應(yīng)該優(yōu)化算法。

優(yōu)化算法的一個途徑是盡量縮小查找范圍。例如,假設(shè)用戶在使用上述的雇員技能數(shù)據(jù)庫的過程中,希望找出既會講日語,又會講法語的所有雇員。如果某公司只有5位雇員會講日語,會講法語的雇員卻有200人,則應(yīng)該先查找會講日語的雇員,然后再從這些會講日語的雇員中查找同時又會講法語的人。

3.保留派生屬性

通過某種運算而從其他數(shù)據(jù)派生出來的數(shù)據(jù)是一種冗余數(shù)據(jù)。通常把這類數(shù)據(jù)“存儲”(或稱為“隱藏”)在計算它的表達式中。如果希望避免重復(fù)計算復(fù)雜表達式所帶來的開銷,可以把這類冗余數(shù)據(jù)作為派生屬性保存起來。

派生屬性既可以在原有類中定義,也可以定義新類,并用新類的對象來保存它們。每當修改了基本對象之后,所有依賴于它的、保存派生屬性的對象也必須進行相應(yīng)的修改。10.10.3調(diào)整繼承關(guān)系

1.抽象與具體

在設(shè)計類繼承時,很少使用純粹自頂向下的方法。通常的作法是,首先創(chuàng)建一些滿足具體用途的類,然后對它們進行歸納,一旦歸納出一些通用的類以后,往往可以根據(jù)需要再派生出具體類。在進行了一些具體化(即專門化)的工作之后,也許就應(yīng)該再次歸納了。對于某些類繼承來說,這是一個持續(xù)不斷的演化過程。

圖10.10用一個人們在日常生活中熟悉的例子來說明上述從具體到抽象,再到具體的過程。圖10.10設(shè)計類繼承的例子(a)先創(chuàng)建一些具體類;(b)歸納出抽象類;(c)進一步具體化;(d)再次歸納

2.為提高繼承程度而修改類定義

如果在一組相似的類中存在公共的屬性和公共的行為,則可以把這些公共的屬性和行為抽取出來放在一個共同的祖先類中,供其子類繼承,如圖10.10(a)和(b)所示。在對現(xiàn)有類進行歸納的時候,要注意下述兩點:

(1)不能違背領(lǐng)域知識和常識。

(2)應(yīng)該確?,F(xiàn)有類的協(xié)議(即同外部世界的接口)不變。

更常見的情況是,各個現(xiàn)有類中的屬性和行為(操作)雖然相似卻并不完全相同。在這種情況下需要對類的定義稍加修改,這樣才能定義一個基類供其子類從中繼承需要的屬性或行為。有時抽象出一個基類之后,在系統(tǒng)中暫時只有一個子類能從它那繼承屬性和行為,顯然,在當前情況下抽象出這個基類并沒有獲得共享的好處。但是,這樣做通常是值得的,因為將來可能重用這個基類。

3.利用委托實現(xiàn)行為共享

僅當存在真實的一般—特殊關(guān)系(即子類確實是父類的一種特殊形式)時,利用繼承機制實現(xiàn)行為共享才是合理的。有時程序員只想用繼承作為實現(xiàn)操作共享的一種手段,并不打算確保基類和派生類具有相同的行為。在這種情況下,如果從基類繼承的操作中包含了子類不應(yīng)有的行為,則可能引起麻煩。例如,假設(shè)程序員正在實現(xiàn)一個Stack(后進先出棧)類,類庫中已經(jīng)有一個List(表)類。如果程序員從List類派生出Stack類,則如圖10.11(a)所示:把一個元素壓入棧,等價于在表尾加入一個元素;把一個元素彈出棧,相當于從表尾移走一個元素。但是,與此同時,也繼承了一些不需要的表操作。例如,從表頭移走一個元素或在表頭增加一個元素。萬一用戶錯誤地使用了這類操作,Stack類將不能正常工作。圖10.11用表實現(xiàn)棧的兩種方法如果你只想把繼承作為實現(xiàn)操作共享的一種手段,則利用委托(即把一類對象作為另一類對象的屬性,從而在兩類對象間建立用繼承實現(xiàn)或用委托實現(xiàn)的組合關(guān)系)也可以達到同樣的目的,而且這種方法更安全。使用委托機制時,只有有意義的操作才委托另一類對象實現(xiàn),因此,不會發(fā)生因不慎而繼承了無意義或是有害操作的問題。

圖10.11(b)描繪了委托List類實現(xiàn)Stack類操作的方法。Stack類的每個實例都包含一個私有的List類實例(或指向List類實例的指針)。Stack對象的操作push(壓棧),委托List類對象通過調(diào)用last(定位到表尾)和add(加入一個元素)操作實現(xiàn),而pop(出棧)操作則通過List的last和remove(移走一個元素)操作實現(xiàn)。

10.11面向?qū)ο蠓治雠c設(shè)計實例

10.11.1面向?qū)ο蠓治?/p>

1.需求

C++類庫管理系統(tǒng)的主要用途,是管理用戶在用C++?語言開發(fā)軟件的漫長過程中逐漸積累起來的類,以便在今后的軟件開發(fā)過程中能夠從庫中方便地選取出可重用的類。它應(yīng)該具有編輯(包括添加、修改和刪除)、存儲和瀏覽等基本功能,下面是對它的具體需求。

●管理用C++?語言定義的類。

●用戶能夠方便地向類庫中添加新的類,并能建立新類庫中原有類的關(guān)系。

●用戶能夠通過類名從類庫中查詢出指定的類?!裼脩裟軌虿榭椿蛐薷呐c指定類有關(guān)的信息(包括數(shù)據(jù)成員的定義、成員函數(shù)的定義及這個類與其他類的關(guān)系)。

●用戶能夠從類庫中刪除指定的類。

●用戶能夠在瀏覽窗口中方便、快速地瀏覽當前類的父類和子類。

●具有“聯(lián)想”瀏覽功能,也就是說,可以把當前類的某個子類或父類指定為新的當前類,從而瀏覽這個新當前類的父類和子類。

●用戶能夠查看或修改某個類的指定成員函數(shù)的源代碼。

●本系統(tǒng)是一個簡化的多用戶系統(tǒng),每個用戶都可以建立自己的類庫,不同類庫之間互不干擾?!駥τ谟脩舻恼`操作或錯誤的輸入數(shù)據(jù),系統(tǒng)能給出適當?shù)奶崾拘畔?,并且仍然繼續(xù)穩(wěn)定地運行。

●系統(tǒng)易學易用,用戶界面應(yīng)該是GUI的。

2.建立對象模型

(1)確定問題域中的類。從對這個C++類庫管理系統(tǒng)的需求不難看出,組成這個系統(tǒng)的基本對象是“類庫”和“類”。類是類庫中的“條目”,不妨把它稱為“類條目(ClassEntry)”。

類條目中應(yīng)該包含的信息(即它的屬性)主要有類名、父類列表、成員函數(shù)列表和數(shù)據(jù)成員列表。一個類可能有多個父類(多重繼承),對于它的每個父類來說,應(yīng)該保存的信息主要是該父類的名字、訪問權(quán)及虛基類標志(是否是虛基類)。對于每個成員函數(shù)來說,主要應(yīng)該保存函數(shù)名、訪問權(quán)、虛函數(shù)標志(是否是虛函數(shù))、返回值類型、參數(shù)及函數(shù)代碼等信息。在每個數(shù)據(jù)成員中主要應(yīng)該記錄數(shù)據(jù)名、訪問權(quán)和數(shù)據(jù)類型等信息。我們把“父類”、“成員函數(shù)”和“數(shù)據(jù)成員”也都作為對象。

根據(jù)對這個C++類庫管理系統(tǒng)的需求可以想到,類條目應(yīng)該提供的服務(wù)主要是:設(shè)置或更新類名;添加、刪除和更改父類;添加、刪除和更改成員函數(shù);添加、刪除和更改數(shù)據(jù)成員。類庫包含的信息主要是庫名和類條目列表。類庫應(yīng)該提供的服務(wù)主要是:向類庫中插入一個類條目;從類庫中刪除一個類條目;把類庫存儲到磁盤上;從磁盤中讀出類庫(放到內(nèi)存中)。

(2)分析類之間的關(guān)系。在C++類庫管理系統(tǒng)的問題域中,各個類之間的邏輯關(guān)系相當簡單。分析系統(tǒng)需求并結(jié)合關(guān)于C++語言語法的知識,可以知道問題域中各個類之間的關(guān)系是:一個用戶擁有多個類庫,每個類庫由0或多個類條目組成,每個類條目由0或多個父類、0或多個數(shù)據(jù)成員及0或多個成員函數(shù)組成。圖10.12是本問題域的對象模型。

C++類庫管理系統(tǒng)的功能和控制流程都比較簡單,無須建立動態(tài)模型和功能模型,僅用對象模型就可以很清楚地描述這個系統(tǒng)了。事實上,在用面向?qū)ο蠓椒ㄩ_發(fā)軟件的過程中,最關(guān)鍵的工作就是建立系統(tǒng)對象模型。圖10.12類庫管理系統(tǒng)的對象模型10.11.2面向?qū)ο笤O(shè)計

1.設(shè)計類庫結(jié)構(gòu)

通常,類庫中包含一組類,這一組類通過歸納、組合等關(guān)系組成一個有機的整體。其中,歸納(即繼承)關(guān)系對于重用來說具有特別重要的意義。

至少有兩種數(shù)據(jù)結(jié)構(gòu)可用來把類條目組織成類庫:一種是二叉樹,另一種是鏈表。

當用二叉樹來存儲類條目的時候,左孩子是子類,右孩子是兄弟類(即具有相同父類的類)。這種結(jié)構(gòu)的優(yōu)點是:存儲結(jié)構(gòu)直接反映了類的繼承關(guān)系;容易查找當前類的子類和兄弟類。缺點是:遍歷二叉樹的開銷較大,不論用何種方法遍歷都需占用大量內(nèi)存;插入、刪除的算法比較復(fù)雜;不易表示有多個父類的類。當用鏈表存儲類條目的時候,鏈表中每個結(jié)點都是一個類條目。這種結(jié)構(gòu)的優(yōu)點是:結(jié)構(gòu)、插入和刪除的算法都相當簡單;容易遍歷。缺點是這種存儲結(jié)構(gòu)并不反映繼承關(guān)系。

由于C++?語言支持多重繼承,類庫中相當多的類可能具有多個父類,因此,容易表示具有多個父類的類應(yīng)該作為選擇類庫結(jié)構(gòu)的一條準則。此外,簡單、方便、容易實現(xiàn)編輯操作和容易遍歷,對這個系統(tǒng)來說也很重要。經(jīng)過權(quán)衡,我們決定采用鏈表結(jié)構(gòu)來組織類庫。因為在每個類條目中都有它的父類列表,查找一個類的父類非常容易,查找一個類的子類則需遍歷類庫,雖然開銷較大但算法卻相當簡單。為了提高性能,可以增加冗余關(guān)聯(lián)(即建立索引),以加快查找子類的速度。

2.設(shè)計問題域子系統(tǒng)

通過面向?qū)ο蠓治?,我們對問題域已經(jīng)有了較深入的了解,圖10.12給出了我們對問題域的認識。在面向?qū)ο笤O(shè)計過程中,僅需從實現(xiàn)的角度出發(fā),并根據(jù)我們所設(shè)計的類庫結(jié)構(gòu),對圖10.12所示的對象模型做一些補充和細化。

(1)類條目(ClassEntry)。類條目的數(shù)據(jù)成員“父類列表”、“成員函數(shù)列表”和“數(shù)據(jù)成員列表”都采用鏈表結(jié)構(gòu)來存儲。因此,在每個類條目的數(shù)據(jù)成員中,應(yīng)該用“父類鏈表頭指針”、“成員函數(shù)鏈表頭指針”和“數(shù)據(jù)成員鏈表頭指針”分別取代原來比較抽象的“父類列表”、“成員函數(shù)列表”和“數(shù)據(jù)成員列表”。為了保存對每個類條目的說明信息,應(yīng)該增加一個數(shù)據(jù)成員“注釋”。此外,類庫中的各個類條目需要組成一條類鏈。因此,在類條目中還應(yīng)該增加一個數(shù)據(jù)成員“指向下一個類條目的指針”。

類條目除了應(yīng)該提供10.11.1節(jié)中所述的那些服務(wù)之外,為了實現(xiàn)提出的需求,還應(yīng)該再增加下列服務(wù):查找并取出指定父類的信息;查找并取出指定成員函數(shù)的信息;查找并取出指定數(shù)據(jù)成員的信息。

(2)類庫(ClassEntryLink)。由于采用鏈表結(jié)構(gòu)實現(xiàn)類庫,每個類庫實際上就是一條類鏈,因此把類庫稱為類條目鏈(ClassEntryLink)。類庫的數(shù)據(jù)成員“類條目列表”具體化為“類鏈頭指針”。

一般來說,實用的類庫管理系統(tǒng)應(yīng)該采用數(shù)據(jù)庫來存儲類庫。在我們這個簡化的實例中,為了簡化處理,決定使用標準的流式文件存儲類庫。

類庫應(yīng)該提供的服務(wù)主要有:取得庫中類條目的個數(shù);讀文件并在內(nèi)存中建立類鏈表;把內(nèi)存中的類鏈表寫到文件中;插入一個類條目;刪除一個類條目;按類名查找類條目并把內(nèi)容復(fù)制到指定地點。

(3)父類(ClassBase)、成員函數(shù)(ClassFun)和數(shù)據(jù)成員(ClassData)。為了構(gòu)造屬于一個類條目的父類列表、成員函數(shù)列表和數(shù)據(jù)成員列表,在ClassBase、ClassFun和ClassData這三個類中除了應(yīng)該定義10.11.1節(jié)中提到的那些數(shù)據(jù)成員之外,還應(yīng)該分別增加數(shù)據(jù)成員“指向下一個父類的指針”、“指向下一個成員函數(shù)的指針”和“指向下一個數(shù)據(jù)成員的指針”。

綜上所述,我們可以畫出類庫(ClassEntryLink)的示意圖(見圖10.13)。圖10.13類庫示意圖

(4)類條目緩沖區(qū)(ClassEntryBuffer)。當編輯或查看類信息時,每個時刻用戶只能面對一個類條目,我們把這個類稱為當前類。為便于處理當前類,額外設(shè)置一個類條目緩沖區(qū),它是從ClassEntry類派生出來的類,除了繼承ClassEntry類中定義的數(shù)據(jù)成員和成員函數(shù)之外,主要增加了一些用于與窗口或類鏈交換數(shù)據(jù)的成員函數(shù)。

每當用戶要查看或編輯有關(guān)指定類的信息時,就把這個類條目從類庫(即類鏈)中取到類條目緩沖區(qū)中。用戶對這個類條目所做的一切編輯操作都只針對緩沖區(qū)中的數(shù)據(jù),如果用戶在編輯操作完成后不“確認”他的操作,則緩沖區(qū)中的數(shù)據(jù)不送回類庫,因而也就不會修改類庫的內(nèi)容。

3.設(shè)計人機交互子系統(tǒng)

1)窗口

為方便用戶使用,本系統(tǒng)采用圖形用戶界面。主要設(shè)計了下述一些窗口:

(1)登錄窗口。啟動系統(tǒng)后即進入登錄(即注冊)窗口,它有一個編輯框供用戶輸入賬號,一個賬號與一個類庫相對應(yīng)。事實上,用戶輸入的賬號就是類庫的庫名。如果在磁盤上已經(jīng)存有與用戶登錄的賬號相對應(yīng)的類庫文件,則在用戶注冊后,系統(tǒng)自動把文件中的數(shù)據(jù)讀出到類鏈中,以便用戶處理。

登錄窗口中設(shè)置了“確認”和“放棄”按鈕。

(2)主窗口。用戶注冊之后進入主窗口,它有“創(chuàng)建”、“瀏覽”、“存儲”和“退出”四個按鈕。

單擊“創(chuàng)建”按鈕則進入創(chuàng)建窗口,在此窗口可以完成創(chuàng)建新的類條目或編輯原有類條目的功能。

單擊“瀏覽”按鈕則進入選擇瀏覽方式窗口,可以選擇適合自己需要的瀏覽方式,以瀏覽感興趣的類。

單擊“存儲”按鈕,則把內(nèi)存中的類鏈保存到磁盤文件中。

單擊“退出”按鈕,則結(jié)束本系統(tǒng)的運行,退回到Windows操作系統(tǒng)。

(3)創(chuàng)建窗口。創(chuàng)建窗口有一個類名組合框,用于輸入新類名或從已有類的列表中選擇類名。類名指定了當前處理的類條目。該窗口有三個分組框,分別管理對當前類的父類、成員函數(shù)和數(shù)據(jù)成員的處理。此外,該窗口還有一個編輯框,用于輸入和編輯對這個類條目的說明信息。

上述三個分組框的每一個框中都有一個列表框,用戶可以從中選擇父類名(或成員函數(shù)名,或數(shù)據(jù)成員名)。此外,每個分組框中都有“添加”、“編輯”和“刪除”等三個按鈕。在不同分組框中單擊“添加”或“編輯”按鈕,將分別彈出父類編輯窗口、成員函數(shù)編輯窗口或數(shù)據(jù)成員編輯窗口。在所彈出的子窗口中可以完成添加新父類(或成員函數(shù),或數(shù)據(jù)成員)或修改已有的父類(或成員函數(shù),或數(shù)據(jù)成員)的信息的功能。這三個子窗口相對來說都比較簡單,為節(jié)省篇幅,就不再單獨講述它們了。讀者可以自行設(shè)計這三個子窗口。單擊“刪除”按鈕,將刪除指定的一個父類(或成員函數(shù),或數(shù)據(jù)成員)。

在創(chuàng)建窗口中還設(shè)有“確認”和“放棄”按鈕,單擊這兩個按鈕中的某一個,將保留或放棄所創(chuàng)建(或編輯)的類條目。

(4)選擇瀏覽方式窗口。目前,本系統(tǒng)僅設(shè)計了兩種瀏覽方式,分別是按類名瀏覽和按類關(guān)系瀏覽。因此,瀏覽方式窗口內(nèi)設(shè)有一個分組框,框內(nèi)有兩個單選按鈕,分別代表按類名瀏覽和按類關(guān)系瀏覽。此外,本窗口內(nèi)還有“確認”和“放棄”兩個按鈕。①類名瀏覽窗口。如果用戶選定按類名瀏覽方式,則進入類名瀏覽窗口。該窗口有一個組合框,用戶可以在這個框中輸入類名,也可以從已有類的列表中選出一個類作為當前類。當用戶通過類名指定了當前類之后,則在該窗口的一個編輯框中顯示這個當前類的說明信息(即注釋),并

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論