面向對象分析與設計 課件 第9-11章 UML模型與程序設計、面向對象的軟件設計原則、設計模式及其應用_第1頁
面向對象分析與設計 課件 第9-11章 UML模型與程序設計、面向對象的軟件設計原則、設計模式及其應用_第2頁
面向對象分析與設計 課件 第9-11章 UML模型與程序設計、面向對象的軟件設計原則、設計模式及其應用_第3頁
面向對象分析與設計 課件 第9-11章 UML模型與程序設計、面向對象的軟件設計原則、設計模式及其應用_第4頁
面向對象分析與設計 課件 第9-11章 UML模型與程序設計、面向對象的軟件設計原則、設計模式及其應用_第5頁
已閱讀5頁,還剩473頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第9章UML模型與程序設計學習目標

通過對各種元素到應用程序映射規(guī)律的討論,理解和掌握軟件建模與系統(tǒng)實現之間的關系

重點掌握類圖模型中的類、關系等模型元素到程序代碼的映射方法

理解和掌握UML中順序圖到程序代碼的映射方法

理解和掌握UML中狀態(tài)圖到程序代碼的映射方法第9章UML模型與程序設計軟件開發(fā)過程中,在完成了軟件建模之后,接下來的工作就是將這些模型轉換成具體的程序設計語言代碼。常見的做法是,使用建模軟件中的“正向工程”功能將模型中的結構模型轉換成相應的應用程序框架代碼,程序設計人員可以此框架代碼為基礎,添加模型中尚未實現的細節(jié),完成系統(tǒng)的程序設計。目前,大多數UML建模軟件,還不能將所有的模型元素以自動化的方式轉換成程序代碼,普遍能夠自動轉換的可能僅有類圖模型。盡管如此,各種模型中的模型元素與應用程序之間仍然存在著千絲萬縷的聯(lián)系。使用UML模型建模一個軟件,可以為開發(fā)人員生成一個較為完善的程序代碼框架。同時,UML中的各種圖形化模型也為開發(fā)人員設計和實現目標系統(tǒng)提供了直觀且無二義性的支持作用。第9章UML模型與程序設計UML模型中,類和類圖是最重要的模型元素,它們描述了構建目標系統(tǒng)所需要的類和類之間的關系、這些類所具有的屬性和方法,同時也包括了這些元素之上的各種約束。盡管UML中定義了種類繁多的模型元素,但它們中的大多數都是面向軟件開發(fā)人員的。本章將以C++程序設計語言為例,討論UML模型向程序代碼映射的基本原理和基本方法,重點討論類圖到C++類的映射,其中包括類之間各種關系的映射。最后,再簡單討論一下模型中的順序圖、通信圖、活動圖和狀態(tài)圖等模型到C++程序的映射。9.1類的映射從靜態(tài)結構的角度來看,任何一個C++程序均可看成是一個由多個類的定義和實現構成的集合。因此,將一個UML模型映射到C++程序的本質,就是將在UML中定義的類轉換成C++程序表示的類。為了敘述方便,本書將UML類圖中的類簡稱為UML類,而將C++中的類簡稱為C++類。9.1.1C++類的基本結構C++程序中,類的定義通常由類名、數據成員和函數成員等三個部分組成。C++程序設計語言通常將每個類的描述分為定義和實現兩個部分,類的定義部分從整體上描述類的基本結構及其與相關類之間的關系,存放在類定義文件(擴展名為.h文件)中。而類的實現部分則是類中每個函數成員的具體實現,一般情況下存放在類的實現文件(擴展名為.cpp文件)中。9.1.1C++類的基本結構類的結構元素包括:(1)類名:C++中的類等同于類型,類名實際上也是一個類型聲明符,可用它聲明對象。(2)數據成員:也就是類屬性,C++類可以沒有數據成員,也可以有多個數據成員。(3)函數成員:即所謂的類方法,C++類中的成員函數分為函數聲明和函數實現。函數聲明屬于類定義,存放在類的定義文件中。函數實現則屬于類的實現部分,存放在類的實現文件中。實際上,函數成員描述了一個類的對象所能提供的服務。一個類可包含多個成員函數。9.1.1C++類的基本結構C++對類的數據成員和函數成員都提供了可見性定義,C++中的可見性分為私有(private),受護(protected)和公有(public)等三種類型。9.1.2UML類到C++類的映射在將一個UML類映射為相應的C++類時,通常分別生成一個頭文件和一個實現文件。頭文件應給出類的定義部分,包括類名、數據成員和函數成員的聲明部分。實現文件則應給出這個類的框架(無具體實現代碼的成員函數),其具體實現細節(jié)則由程序人員自行設計和添加,或由某種建模軟件根據模型中的其他信息自動生成。9.1.2UML類到C++類的映射例如,圖9-1給出了一個CLine類,其中定義了兩個數據成員和三個函數成員。可直觀地看出其所有成員的可見性。由這個UML類生成的C++代碼如下所示:圖9-1CLine類//File:CLine.hclassCLine:publicCGraphElement{public:

CLine();

virtual~CLine();

voidShift(intdy,intdx);

voidRotate(doublealpha);

voidDraw(CDC*pDC);private:

CPointstart,end;};//File:CLine.cpp#include"CLine.h"CLine::CLine(){}CLine::~CLine(){}voidCLine::Shift(intdy,intdx){}voidCLine::Rotate(doublealpha){}voidCLine::Draw(CDC*pDC){}9.1.2UML類到C++類的映射CLine類的映射非常簡單,其中只包含了屬性的映射和方法的映射。實際上,UML類的映射遠比這里所描述的復雜得多,類之間通常存在著泛化、關聯(lián)(聚合、組合)和依賴等關系。在將UML類映射為C++類時,類之間的這些關系也必須進行映射。9.1.3屬性和方法的映射UML通常使用各種修飾符或屬性值來描述類屬性和方法的可見性、作用域、抽象類、抽象方法等方面的特性或約束。C++類中,屬性和方法的可見性定義與UML類中的可見性定義完全相同,不同的僅僅是表示符號不同而已。C++使用靜態(tài)成員表示具有類作用域的屬性和方法。C++類中,靜態(tài)成員的含義與UML類中類作用域的含義完全一致。同樣,UML類中實例作用域的含義與C++類中的普通成員的含義也是相同的。9.1.3屬性和方法的映射表9-1常見的UML類修飾符以及對應的C++表示方法類特性UML修飾符C++關鍵字說明可見性公共+public表示屬性或方法對任何類均是可見的私有-private表示屬性或方法只在本類中可見保護#protected表示屬性或方法只在本類及派生類中可見作用域實例(默認)默認C++類的成員默認為實例作用域類(下劃線)staticC++類用靜態(tài)成員表示類作用域抽象操作斜體方法名或abstract純虛函數C++用純虛函數表示抽象操作virtual類型名方法名([參數表])=0抽象類斜體類名

C++用含有純虛函數或將構造函數可見性置為protected的方法表示抽象類方法修飾符QueryconstC++用const關鍵字表示只讀操作,只讀操作不修改對象屬性值Update默認C++類的操作的默認屬性,使用const關鍵字表示只讀操作,只讀操作不修改對象屬性值參數修飾符inconst不允許在方法中修改參數的值或狀態(tài)out或inoutconst&允許在方法中對參數作任何操作9.1.3屬性和方法的映射可以把類作用域方法(靜態(tài)成員函數)看成是為類(類的對象集合)提供的服務,而不是專門為這個類的某個實例提供的服務。因此,這些方法并不與特定的對象相聯(lián)系,當然也不能直接訪問該類的任何實例和具有實例作用域的方法。UML類中使用斜體方法名或abstract關鍵字表示抽象類,C++類則純虛函數或將構造函數定義成保護或私有可見性的方法定義抽象類。二者在表示方法上略有不同,但二者的含義是相同的。如果UML抽象類中不包含抽象方法,那么映射時應將對應的C++類的構造函數的可見性置為保護或私有。這樣,將會使得這個類因不能實例化而變成抽象類。9.1.3屬性和方法的映射將UML類中的抽象操作映射到C++類時,可使用帶有virtual關鍵字的純虛函數表示,純虛函數的語法形式表示為:virtual類型名方法名([參數表])=0。在這一點上,二者的表示法和語義也是相同的。其共同特征是:基類中都沒有給出相應的實現,其實現被推遲到它的某個派生類。包含抽象操作的類本身就是抽象類,它不能被實例化。另外,UML類中某些方法的特性中可能會出現query或update關鍵字。特性query的含義是該方法的執(zhí)行不會修改該對象的任何屬性值,即它對對象屬性的訪問時只讀的。與此相對的是,特性update表明該方法可以修改對象中的屬性值,即它可以對對象中的屬性進行讀寫訪問。9.1.3屬性和方法的映射C++類操作的默認特性是讀寫的,類操作的query特性可以用帶有const關鍵字的成員函數表示。C++類中被聲明為const的成員函數,只能對對象中的數據成員進行只讀訪問而不進行寫訪問。任何不帶有const關鍵字的成員函數被看成是需要修改對象數據成員的函數,而且編譯程序不允許為一個const對象調用這個函數。如果僅僅在類頭中將一個函數聲明為const,那么就不能保證成員函數也是這樣定義的,所以編譯程序迫使程序人員在定義函數時要重申const說明。為確保函數的只讀特性,在const函數中,任何一個修改成員變量值的語句或非const成員函數的調用都會觸發(fā)一個編譯錯誤,以保證函數對對象狀態(tài)的保護作用。9.1.3屬性和方法的映射在UML類中,每個方法可帶有若干個形式參數,每個參數的語法形式如下:參數類別形式參數名:類型[=默認值];其中參數類別的取值可以包括{in,out,inout}三個選項,用于表示參數的可修改性語義。參數類別取值為in時,表示在方法內只能對這個參數進行讀訪問,而不能進行寫訪問;當參數類別為out時,表明該參數為輸出參數,在方法體內可調用參數對象的寫訪問;當類別為inout時,表明方法體內可對參數它進行任何訪問。9.1.3屬性和方法的映射在C++中,可用關鍵字const限定函數參數的可修改性。如果函數中出現了對const類型的參數進行寫操作語句,那么編譯程序會給出一個出錯信息。構造函數和析構函數是兩種特殊方法。程序在創(chuàng)建對象時會自動調用構造函數,以便完成對象的初始化工作。在C++中,構造函數名必須與類名相同,它沒有返回值。析構函數也用類的名做函數名,只不過前面加一個特殊符號“~”以便和構造函數區(qū)分開。它不帶任何參數,也沒有返回值,其目的是用來為對象做一些清除性的工作。9.1.3屬性和方法的映射在映射時,如果在UML類中沒有用衍型?constructor?和?destructor?修飾方法,那么一般應自動生成默認的構造函數和析構函數。在C++中,復制構造函數采用相同類型的對象引用作為它的參數,它可用來從現有的對象創(chuàng)建新的對象。當用傳值方式傳遞或返回一個對象時,編譯程序就自動調用該復制函數。如果UML類涉及指針的管理,那么為保證對指針進行正確的操作,同時還應自動生成復制構造函數及進行“=”操作符重載。9.1.3屬性和方法的映射當UML類中存在抽象方法,即相應的C++類包含虛函數時,那么在映射時應自動生成虛析構函數而不是默認的析構函數。當UML類中包含子類時,父類映射所得的C++類的析構函數也應為虛析構函數,虛析構函數的目的是保證正確地清除對象。9.1.3屬性和方法的映射因此,在把UML類映射為C++類時,一般應遵循如下映射規(guī)則。(1)類、屬性和方法的映射根據類圖中定義的類名、屬性及方法定義類。包括類的定義和類的實現。了定義存放在頭文件中,類實現存放在.cpp文件中。(2)可見性的映射將UML類中用+、-與#修飾的屬性或方法分別映射成帶有public,private與protected等關鍵字數據成員或成員函數。9.1.3屬性和方法的映射因此,在把UML類映射為C++類時,一般應遵循如下映射規(guī)則。(1)類、屬性和方法的映射根據類圖中定義的類名、屬性及方法定義類。包括類的定義和類的實現。了定義存放在頭文件中,類實現存放在.cpp文件中。(2)可見性的映射將UML類中用+、-與#修飾的屬性或方法分別映射成帶有public,private與protected等關鍵字數據成員或成員函數。9.1.3屬性和方法的映射(3)作用域映射將UML類中的具有類作用域的屬性或方法分別映射成帶有static關鍵字的靜態(tài)數據或函數成員。(4)構造函數和析構函數在C++類中添加默認構造函數和析構函數。(5)抽象方法映射將UML類中的抽象方法(方法名為斜體或后面帶有abstract關鍵字)映射成純虛函數。9.1.3屬性和方法的映射(6)設置成員函數的只讀屬性將UML類中query特性為真的方法映射成帶有const關鍵字的方法,同時將UML類方法形式參數帶有的{in,out,inout}中的具體選項映射成對應的C++類成員函數的形式參數。設UML類中某個參數的數據類型為T,則其具體映射方法如下:①若參數的類別為in,則應將該參數類型映射為constT&;②若參數的類別為out或inout,則可將該參數類型映射為T&;9.1.3屬性和方法的映射(7)帶有泛化關系的UML類的映射若映射的UML類之間存在泛化關系,則將相應C++類的析構函數設置成虛函數。(8)抽象類的映射若UML類是一個抽象類,則構造函數的可見性將被映射為保護的(protected)。9.1.3屬性和方法的映射圖9-2中的類圖中包含了文檔CGraphicDocument、圖形元素CGraphElement、直線Cline和圓CCircle等四個類,還包含了兩個繼承和一個關聯(lián)關系。圖9-2圖形文檔結構類9.1.3屬性和方法的映射按照上述規(guī)則,從這個類圖生成的C++程序代碼如下。1)CGraphicDocument類的定義與實現

//CGraphicDocument.h#include"CGraphElement.h"classCGraphicDocument{public:

CGraphicDocument();

virtual~CGraphicDocument();

voidSave(CArchivear);

voidAdd(CAgrphicElement&e);

CGraphElement*m_CGraphElement;};//CGraphicDocument.cpp#include"CGraphicDocument.h"CGraphicDocument::CGraphicDocument(){}CGraphicDocument::~CGraphicDocument(){}voidCGraphicDocument::Save(CArchivear){}voidCGraphicDocument::Add(CGraphElement&e){}9.1.3屬性和方法的映射2)CGraphElement類的定義與實現

//CGraphElement.hclassCGraphElement{public:CGraphElement();virtual~CGraphElement();protected:intLineStyle,intLineWidth;COLORREFLineColor;voidDraw(CDC*pDC);voidShift(intdx,intdy);voidRotate(doubleAlpha);};//CGraphElement.cpp#include"CGraphElement.h"CGraphElement::CGraphElement(){}CGraphElement::~CGraphElement(){}voidCGraphElement::Draw(CDC*pDC){}voidCGraphElement::Shift(intdx,intdy){}voidCGraphElement::Rotate(doubleAlpha){}9.1.3屬性和方法的映射3)CCircle類的定義與實現

//CCircle.h#include"CGraphElement.h"classCCircle:publicCGraphElement{public:CCircle();virtual~CCircle();voidDraw(CDC*pDC);voidShift(dx,intdy);voidRotate(doublealpha);private:CPointCenter;intRadius;COLORREFFaceColor;intFaceStyle;};//CCircle.cpp#include"CGraphElement.h"#include"CCircle.h"CCircle::CCircle(){}CCircle::~CCircle(){}voidCCircle::Draw(CDC*pDC){}voidCCircle::Shift(dx,intdy){}voidCCircle::Rotate(doublealpha){}9.1.3屬性和方法的映射4)CLine類的定義與實現

//Cline.h#include"CGraphElement.h"classCLine:publicCGraphElement{public:CLine();virtual~CLine();voidShift(intdy,intdx);voidRotate(doublealpha);voidDraw(CDC*pDC);private:CPointstart,end;};//CLine.cpp#include"CLine.h"CLine::CLine(){}CLine::~CLine(){}voidCLine::Shift(intdy,intdx){}voidCLine::Rotate(doublealpha){}voidCLine::Draw(CDC*pDC){}9.1.3屬性和方法的映射容易看出,這些代碼雖然給出了完整的類定義,但卻僅僅生成了一系列的空方法,這些空方法的實現則被留給了程序員。這時,模型中關于各種模型元素的描述細節(jié)將成為程序員編程的重要依據。9.2泛化關系的映射在面向對象設計方法中,泛化關系用于從一個類中派生出新的類,即向一個泛化類中添加新的信息或對其進行修改而得到新的特化類。C++中,與泛化關系對應的機制是繼承關系,C++不僅支持繼承,而且還支持多繼承的設計。繼承提供了一種能夠促進代碼共享、復用和擴展的重要機制。在繼承關系中,不僅可以在基類的基礎上定義派生類,而且還可以在派生類中添加新的數據成員和函數成員。更重要的是,C++還提供了一種虛函數機制,以便在派生類中覆蓋基類中的某些成員函數。C++規(guī)定,在派生類中可以重新定義那些在基類中被聲明為虛函數的成員函數。9.2泛化關系的映射在C++中,還定義了公有、私有和保護等多種繼承方式,派生類可按公有方式繼承基類,也可按私有方式或受保護的方式繼承基類。1.公有繼承(public)公有繼承的特點是基類的公有成員和保護成員作為派生類的成員時,它們都保持原有的可見性,而基類的私有成員仍然是私有的,不能被這個派生類的子類所訪問。9.2泛化關系的映射2.私有繼承(private)私有繼承的特點是基類的公有成員和保護成員都可以被派生類繼承,但它們在派生類中的可見性被定義為私有的,所以它們也不能被這個派生類的子類訪問。9.2泛化關系的映射3.保護繼承(protected)保護繼承的特點是派生類繼承基類的所有公有成員和保護成員,并把它們定義為派生類的保護成員,當然可以被它的派生類或友元訪問,基類的私有成員仍然是基類私有的。在將UML類中的泛化關系映射為C++類中的繼承關系時,一般選擇公有繼承。9.2泛化關系的映射在多繼承的情況下,有時會出現重復繼承的情況發(fā)生,如圖9-3中的GraduateStudentOnJob類(在職研究生)就重復地繼承了Person類(人員)的屬性,這可能會導致了派生類中屬性的冗余。圖9-3多繼承中的重復繼承9.2泛化關系的映射C++定義了一種被稱為虛繼承的方式來解決這個問題。當使用虛繼承時,不論從派生類到其超類有幾條繼承路徑,派生類都將僅一次性地繼承其虛基類的屬性,這樣就可以有效地避免因多繼承產生的冗余所導致的不一致性。當然,必要時也可以不使用虛繼承。為簡單起見,在將泛化關系向繼承關系映射時,應讓所有的派生類都以虛繼承的方式描述它從基類中的繼承。9.2泛化關系的映射將圖9-3中的多繼承映射到C++后生成的程序代碼如下所示,得到的這些代碼中,所有類之間的繼承就都使用了虛繼承方式來定義這些類之間的泛化。classPerson{public:

Person();

virtual~Person();private:

char*PersonID;

char*Name;};classTeacher:virtualpublicPerson{public:

Teacher();

virtual~Teacher();private:

char*TeacherID;

char*Specialities;};9.2泛化關系的映射將圖9-3中的多繼承映射到C++后生成的程序代碼如下所示,得到的這些代碼中,所有類之間的繼承就都使用了虛繼承方式來定義這些類之間的泛化。classGraduateStudent:virtualpublicPerson{public:

GraduateStudent();

virtual~GraduateStudent();private:

char*StudentID;

char*Director;};classGraduateStudentOnJob:virtualpublicTeacher,virtualpublicGraduateStudent{public:

GraduateStudentOnJob();

virtual~GraduateStudentOnJob();};9.3關聯(lián)關系的映射關聯(lián)關系是對象之間的十分重要的一種關系。關聯(lián)關系不僅存在于系統(tǒng)的應用域中的實體類之間,也存在于系統(tǒng)的分析域、設計域及實現域中的各種類型的類之間。關聯(lián)最重要的含義在于,一個對象可以通過關聯(lián)訪問到與之關聯(lián)對象所提供的任何服務。對象模型將關聯(lián)關系描述成一種類之間的靜態(tài)的結構性的關系。但實際上,關聯(lián)關系卻是對象之間存在的動態(tài)關系。雖然大多數情況下,實例化一個關聯(lián)關系時,往往是簡單地實例化幾個對象,然后再建立它們之間的聯(lián)系就可以了。但很多情況下,對象之間的關聯(lián)卻是選擇性的,還可能需要一個相對復雜的過程來實例化一個需要的關聯(lián)。9.3關聯(lián)關系的映射影響關聯(lián)映射的因素有很多,如關聯(lián)的方向性、多重性、強制性、有序性、帶有關聯(lián)類的關聯(lián)、帶有限定符、聚合關系和組合關系等,所有這些因素都會對關聯(lián)的映射產生較大的影響。實現關聯(lián)映射最重要的問題是準確把握這些關聯(lián)的實質性含義。在C++程序設計語言中,實現關聯(lián)關系的基本方法是在關聯(lián)的起始端的類中嵌入一個指向被關聯(lián)對象的指針,通過這個指針,這個對象可以在其內部的任何位置訪問被關聯(lián)對象提供的服務。在映射時,可以將關聯(lián)端點上的角色名映射為一個屬性(指向被關聯(lián)對象的指針),其可見性一般設置為private。有時為了維護對象之間的關聯(lián)關系,相應的C++類中還應添加對指針進行讀寫操作的訪問成員函數。9.3.1關聯(lián)的方向性從關聯(lián)的多重性的角度來看,關聯(lián)可以分成單向關聯(lián)和相關聯(lián)兩種情況。如圖9-4就給出了單向關聯(lián)和雙向關聯(lián)的例子。單向關聯(lián)的含義是關聯(lián)中A類對象可以通過這個關聯(lián)訪問B類對象。反之,B類對象卻不能通過這個關聯(lián)訪問A類對象。雙向關聯(lián)的含義是關聯(lián)中任何一端的對象都可以通過關聯(lián)訪問另一端的對象。圖9-4單向關聯(lián)和雙向關聯(lián)a)單向關聯(lián)b)雙向關聯(lián)9.3.1關聯(lián)的方向性1)單向關聯(lián)的映射

classA{private:B*m_B;public:A();virtual~A();};classB{public:B();virtual~B();};2)雙向關聯(lián)的映射

classA{private:B*m_B;public:A();virtual~A();};classB{private:A*m_A;public:B();virtual~B();};這兩種情況的關聯(lián)映射出來的C++類定義如下9.3.2多重性與關聯(lián)映射關聯(lián)角色在類中的具體實現還依賴于關聯(lián)的多重性。通常情況下,關聯(lián)角色的多重性一般可分為0..1、1、0..*和1..*等多種情況,關聯(lián)的兩個關聯(lián)角色含有一個多重性。這可以使關聯(lián)組合出多種不同的情況,映射時需要關注的是關聯(lián)對象之間的關聯(lián)是否滿足特定的多重性要求。實現關聯(lián)多重性即包含了類結構方面的約束,同時還可能包含了算法方面的約束。圖9-4中給出了若干個具有不同的多重性的關聯(lián)的實例,不同的關聯(lián)給系統(tǒng)的實現帶來了不同的約束條件,將它們映射到程序設計語言所得到的結果也會有重要的差別,有時甚至會有很大的區(qū)別。探究這些差別將有助于更深刻地理解關聯(lián)的建模意義和編程方面的意義,這些區(qū)別將主要體現在類的關聯(lián)角色屬性定義、類的方法、關聯(lián)對象的實例化以及這些方法的使用等多個方面。9.3.2多重性與關聯(lián)映射圖9-5關聯(lián)的多重性強制對可選的一對一關聯(lián)b)強制對強制的一對一關聯(lián)c)強制對可選的一對多關聯(lián)d)可選對可選的一對多關聯(lián)9.3.2多重性與關聯(lián)映射強制對可選的關聯(lián)的類定義classA{private:B*m_B;public:A();virtual~A();voidSetB(B*b);B*GetB();};classB{private:A*m_A;public:B(A&a);virtual~B();};強制對可選的關聯(lián)的類實現

#include"A.h"A::A(){}A::~A(){}voidA::SetB(B*b){m_B=b;}B*A::GetB(){returnm_B;}#include"B.h"B::B(A*a){m_A=a;}B::~B(){}9.3.2多重性與關聯(lián)映射強制對可選一對一關聯(lián)創(chuàng)建和使用圖9-5中a表示的強制對可選一對一關聯(lián)的示例如下:1創(chuàng)建任何一個B類的實例時,必須先創(chuàng)建相應的類A的實例,并創(chuàng)建這兩個對象的鏈接關系。創(chuàng)建過程如下:A*a=newA(); //首先,創(chuàng)建A類實例a。B*b=newB(*a); //創(chuàng)建與a關聯(lián)的B類實例ba.SetB(*b); //設置對象a到對象b的關聯(lián)。9.3.2多重性與關聯(lián)映射2需要單獨創(chuàng)建A類實例時,可不必創(chuàng)建類B的實例,也不必創(chuàng)建這個關聯(lián)的實例。A類實例以單獨的身份履行它所承擔的系統(tǒng)責任。創(chuàng)建過程如下:A*a=newA();3撤銷A類對象時,如果存在與其關聯(lián)的B類對象,那么應首先撤銷這個B類對象,然后再撤銷這個A類對象。撤銷過程如下:if(!a->GetB()){deletea->GetB();}deletea;9.3.2多重性與關聯(lián)映射4撤銷B類對象時,如果存在與其關聯(lián)的A類對象,那么應首先在A類對象中注銷這個關聯(lián),然后再撤銷這個B類對象。撤銷過程如下:if(!b->GetA()){b->SetA(NULL); //在A類對象中注銷這個關聯(lián)}deleteb; //撤銷B類對象9.3.2多重性與關聯(lián)映射2.強制對強制的一對一關聯(lián)而對于圖9-5中b強制對強制的一對一關聯(lián)來說,它所表達的含義則是:對于每一個類A的對象a,必須有一個類B的對象b和從對象a到對象b的鏈接。同時,對于對象b來說,也要求存在一個從對象b到對象a的鏈接。其映射代碼如下所示。強制對可選的關聯(lián)的類定義

classA{private:B*m_B;public:A();virtual~A();voidSetB(B*b);B*GetB();};classB{private:A&m_A;public:B(A&a);virtual~B();};強制對可選的關聯(lián)的類實現

#include"A.h"A::A(){m_B=NULL;}A::~A(){}voidSetB(B*b){m_B=b;}B*GetB(){returnm_B;}#include"B.h"B::B(A&a){m_A=a;}B::~B(){}9.3.2多重性與關聯(lián)映射創(chuàng)建和使用圖9-5中b表示的強制對強制一對一關聯(lián)的示例如下:1關聯(lián)中任何一個類的實例都不能單獨創(chuàng)建,創(chuàng)建類實例時,必須創(chuàng)建兩個類的實例并建立這兩個對象之間的鏈接關系。創(chuàng)建過程如下:A*a=newA(); //首先,創(chuàng)建A類實例a。B*b=newB(*a); //創(chuàng)建與a關聯(lián)的B類實例ba.SetB(*b); //設置對象a到對象b的關聯(lián)。2使用關聯(lián),若兩個關聯(lián)的對象之間具有明確的客戶與服務之間的關系。則二者的使用則可以明確地按照這個關系使用。否則,可以根據使用關聯(lián)的上下文使用這個關聯(lián)。3撤銷對象,必須同時撤銷兩個對象,即撤銷這個關聯(lián)的實例。撤銷過程如下:deletea;deleteb;從上面兩個例子不難看出,理解了關聯(lián)多重性的確切語義,不難完成關聯(lián)到程序設計語言的映射。另外一個問題是,關聯(lián)到程序設計語言的映射方案并不是唯一的,唯一的是二者所表示的語義。9.3.3組合和聚合關系的映射聚合關系是一種特殊的關聯(lián)關系,其特殊性在于它描述了對象之間的整體與部分之間的關系。組合關系則是一種特殊的聚合關系,所不同的是,組合關系強調了整體對象與部分對象具有了相同的生存期的關系。C++程序設計語言中并沒有與聚合和組合關系直接對應的語言成分。在將這類關系映射為C++程序時,與關聯(lián)的實現方式類似,可采用嵌入指針的方式實現聚合關系;一般情況下,可采用嵌入對象的方式實現組合關系,并實現組合關系所強調的相同的生存期特性。換句話說,組合關系中的整體被映射成一個容器對象,個體部分則被實現為容器的嵌入對象。9.3.3組合和聚合關系的映射圖9-6描述了一個訂單類,由訂單和訂單細則兩個類構成,它的語義是任何一個Order類的對象,都是由一組特定的OrderItem類的對象組合而成的,并且這些整體對象(訂單)與它們的子對象(訂單明細)具有相同的生命周期。圖9-6訂單類圖9.3.3組合和聚合關系的映射//訂單類的定義order.h#include"OrderItem.h"classOrder{private:char*OrderID;char*CustomerID;char*CustomerName;char*TotalAmount;charOrderDate;OrderItem*OrderItemList;public:Order();virtual~Order();voidADD(OrderItemitem);boolRemove(iint);};//訂單細則類的定義ordeitem.hclassOrderItem{private:char*OrderID;intnumber;char*GoodsID;char*GoodsName;floatQuantity;public:OrderItem();virtual~OrderItem();};

//訂單類的實現order.cppOrder::Order(){}Order::~Order(){}voidOrder::ADD(OrderItemitem){}boolOrder::Remove(iint){returnfalse;}//訂單細則類的實現ordeitem.hOrderItem::OrderItem(){}OrderItem::~OrderItem(){}

根據從這個類圖生成的C++程序代碼可以看出,這段代碼中只是簡單地將組合關系映射成一個單向的關聯(lián)關系,而把組合關系概念中所強調的整體和部分應具有的相同生命期特性的責任則被留給了程序員,程序員必須在他們編寫的程序中添加能夠實現這樣一種責任的程序代碼。根據這個類圖生成的C++程序代碼如下所示9.3.3組合和聚合關系的映射另外,影響關聯(lián)映射的其他因素,如關聯(lián)對象有序性、關聯(lián)類、限定符等也都可以映射到程序代碼中,具體的映射方法則由程序員負責完成。9.4依賴關系的映射對象之間的依賴體現為一個對象以某種方式訪問了另一個對象,從而導致了兩個對象(或類)之間的依賴。按照對象之間的訪問方式,可將依賴分為成員依賴、參數依賴和局部變量依賴等三種情況。(1)屬性依賴:如果一個類的實例或實例引用是另一個類的屬性時,那么稱這兩個類之間存在屬性依賴。例如:如下程序代碼所示的兩個類,就表示了兩個類之間的屬性依賴。classA{Bb;voidfunca(){b.funcb();}}classB{;voidfuncb();}9.4依賴關系的映射可以看出,類B對象被定義為類A的一個屬性,此時,類A和類B之間存在著一種屬性依賴。顯然,在類A中的任何地方,都可以訪問到與之相對應類B對象b的服務。這時,這個依賴的作用范圍是類A的所有方法。9.4依賴關系的映射2)參數依賴:如果一個類(或對象)以方法的形式參數的形式出現在另一個類中,那么稱這兩個類(或對象)之間存在的關系為參數依賴關系。例如:如下程序代碼所示的兩個類,就表示了兩個類之間的屬性依賴??梢钥闯?,類B的實例b是以形式參數的形式出現在類A的方法中,這時,類A和類B之間存在著一種從A到B的依賴,并且A對B的依賴僅局限在A的方法voidfunca(Bb)的內部。所以參數依賴是一種比屬性依賴弱一些的依賴。classA{……;voidfunca(Bb){b.funcb();}} classB{……;voidfuncb();}9.4依賴關系的映射3)局部變量依賴:如果一個類的實例或實例引用是另一個類的某個方法的局部變量,那么稱這兩個類之間的依賴為局部變量依賴。例如:如下程序代碼所示的兩個類,就表示了兩個類之間的局部變量依賴。顯然,這種A對B的局部變量依賴對A的影響區(qū)域與參數依賴相似。但這兩種依賴仍然是有區(qū)別的,區(qū)別在于局部變量依賴的影響區(qū)域被牢牢地控制在對應方法的某個分程序之內。classA{voidfunca(){Bb;b.funcb();}}classB{voidfuncb();}9.4依賴關系的映射例如,如下Circle類中的函數voiddraw(CDC*pDC),就描述了Circle類與CDC類之間的參數依賴。與上述的局部變量依賴相比較,這個依賴的影響范圍就擴大到整個voiddraw(CDC*pDC)函數。classCircle{intx,y;doubleradius;voiddraw(CDC*pDC){pDC->Ellipse(x,y,radius,radius);}}9.5接口和包的映射9.4.1接口的映射接口是由一組操作構成的集合。如果一個類實現了某個接口中的某些操作,那么就稱這個類實現了這個接口。在C++程序設計語言中,沒有定義專門的表示接口的語法成分,直接表示接口的方法就是定義一個僅包含若干個純虛函數的類來表示接口。將接口映射到C++程序時,可以將接口映射成一個用C++描述的抽象類,或者將抽象類看成是接口。如果映射得到的是一個每個操作都是具有公共可見性的純虛函數的類時,這樣得到的類就是一個純粹的用C++程序設計語言描述的接口。進一步,還可以將接口的實現映射成接口的派生類。9.4.1接口的映射下面將給出一個接口映射的例子。圖9-7接口及其實現9.4.1接口的映射將圖9-7中的接口及其實現映射到C++后,得到的程序代碼如下所示。//接口IList.htemplate<Titem>classIList{public:IList(){}virtual~IList(){}virtualboolAdd(itemT)=0;virtualvoidFirst()=0;virtualTGetCurrent()=0;virtualboolHasItems()=0;virtualboolNext()=0;virtualTRemove(iint)=0;};

//實現ConcreateList.h#include"IList.h"template<Titem>classConcreateList:publicIList<Titem>{public:ConcreateList(){}virtual~ConcreateList(){}virtualboolAdd(itemT){returnfalse;}virtualvoidFirst(){}virtualTGetCurrent(){returnNULL;}virtualboolHasItems(){returnfalse;}virtualboolNext(){returnfalse;}virtualTRemove(iint){returnNULL;}};9.4.2包的映射首先要說明的是,包的映射方法不是唯一的。一般情況下,模型中的包主要用于組織和管理模型中的模型元素,因此,模型中的包也不一定都要映射到程序代碼中去。但對于模型中用于組織某些結構元素(如類等)的包,有時就可能需要這樣的映射了。在UML中,包可以看成是由若干個模型元素構成的集合,使用包可以將一個大系統(tǒng)劃分成多個比較小的子系統(tǒng)。同時,各個包之間還可以存在各種依賴關系。9.4.2包的映射例如,在圖9-8中,給出了List和Order兩個包,其中,Order與List之間,就存在了一個引入(import)依賴。圖9-8IList和Order包及其之間的依賴關系9.4.2包的映射在C++中,可以將包映射成一個名空間(namespace)。名空間可以用來隱藏數據結構的定義,從而防止程序中的命名沖突。當需要引用某個名空間中定義的符號時,可以使用using語句引入這個名字空間,using語句實際上與UML中包之間的某種依賴關系相對應。在映射時,可將選定的包和一個名空間對應,包之間的依賴關系則可以在代碼中使用一個using語句實現。將圖9-6中的接口IList映射到C++程序時,可使用下列形式的代碼實現包的映射。9.4.2包的映射//接口IList的定義IList.hnamespaceIList{template<Titem>classIList{public:IList(){}virtual~IList(){}virtualboolAdd(itemT)=0;virtualTRemove(iint)=0;virtualboolHasItems()=0;virtualvoidFirst()=0;virtualboolNext()=0;virtualTGetCurrent()=0;};}//接口IList的引用usingIListtemplate<Titem>classConcreateList:publicIList{public:ConcreateList(){}virtual~ConcreateList(){}virtualboolAdd(itemT){returnfalse;}virtualvoidFirst(){}virtualTGetCurrent(){returnNULL;}virtualboolHasItems(){returnfalse;}virtualboolNext(){returnfalse;}virtualTRemove(iint){returnNULL;}};9.4.2包的映射代碼中,接口IList被封裝在Ilist包中,需要時,可使用usingnamespaceIList語句引用這個名字空間中的IList接口。9.5UML中其他各種圖的映射UML模型中,類和類圖之外的各種圖與程序代碼之間也都存在著某種形式的映射關系,盡管這些映射不像類或類圖那樣可以直接映射,但它們仍然對最終的系統(tǒng)實現產生重要的影響。很多情況下,這些圖到實現的映射通常是通過對類施加的影響而最終映射到目標系統(tǒng)的。事實上,模型本身也不一定能夠全面描述軟件結構和行為的全部細節(jié),幾乎每一個模型都僅僅是從某一角度或某一側面對系統(tǒng)的概括性描述。雖然,大多數建模軟件都沒有提供這些模型到實現的自動映射方法,但這樣的轉換卻是內在的,也是可行的。9.5.1順序圖的映射在軟件設計過程中,順序圖主要用于對系統(tǒng)的行為建模,通常用于描述系統(tǒng)的一個過程。順序圖到實現的映射并不是直接進行的,其基本思想是通過行為建模不斷豐富和完善系統(tǒng)的類模型,從而完善系統(tǒng)的結構模型。這些動態(tài)模型,包括順序圖、通信圖、狀態(tài)圖和活動圖等,可以為系統(tǒng)帶來的模型增量包括:9.5.1順序圖的映射1.發(fā)現新的類如果動態(tài)模型中出現了新的類,那么就意味著可能為系統(tǒng)找到了新的類。建模過程中,應及時將新發(fā)現的類作為新的模型元素加到你的模型中。2.新的關系如果在動態(tài)模型中出現了新的對象(類)之間的消息傳遞,那么就意味著可能為找到了新的對象之間的鏈接關系。進一步分析這些消息,還可以確認這些關系的具體類型及其他細節(jié),并把它們補充到模型中。9.5.1順序圖的映射3.新的屬性和方法動態(tài)模型中出現的每一個消息,都可能與系統(tǒng)中的某個對象、對象的屬性或方法相對應。新的消息就意味著可能找到了新的對象、屬性或方法。建模過程中,應及時將新發(fā)現的對象(類)、屬性或方法加入到模型中。4.方法的實現細節(jié)動態(tài)模型中,兩個對象之間的消息將被映射成目標對象的某個方法。消息的順序和約束就可能構成了這些方法的實現細節(jié)。如圖9-9給出的一個某商品銷售用例的順序圖描述。圖9-9商品銷售用例的順序圖9.5.1順序圖的映射分析這張順序圖,可以獲得如下一些信息。1)類或對象圖中出現的了銷售員(saler)、訂單窗體(OrderForm)、訂單控制(OrderControl)、數據庫控制(DBControl)、訂單(Order)和訂單明細(OrderItem)等多個生命線元素。除了銷售員是參與者以外,其余的均為系統(tǒng)中的類,它們都將被映射到最終的軟件中去。9.5.1順序圖的映射2)關系分析順序圖中的消息傳遞關系,可得到對象之間應有的鏈接關系。從而分析出這些類之間的關聯(lián)關系。如果觀察每個對象的生命周期,還可以確定出實例化這些關聯(lián)關系的時機和方法。從圖9-9可以得到的關系包括:saler與OrderForm、OrderForm與OrderControl、OrderControl與Order、OrderControl與OrderItem、OrderControl和DBContro以及Order和OrderItem之間的關聯(lián)關系。9.5.1順序圖的映射3)屬性和方法首先,分析參與者(saler)與邊界類(OrderForm)之間的交互,可以設計出邊界類的屬性和方法。包括邊界類中的界面元素、需要響應的事件及事件的響應方法。9.5.1順序圖的映射表9-2列出了從圖9-9可以得到的邊界類所需要的界面元素、相應事件以及事件的相應方法。表9-2邊界類(OrderForm)的界面元素、事件及事件處理方法消息界面元素對應的事件事件響應說明訂貨請求用戶命令激活CreateOrder創(chuàng)建訂單輸入顧客編號字符串輸入完成輸入SetCustomerID輸入訂單中的顧客信息輸入顧客姓名字符串輸入完成輸入SetCustomerName輸入顧客地址字符串輸入完成輸入SetCustomerAddress增加訂單明細用戶命令激活CreateOrderItem增加一條明細記錄輸入商品編號字符串輸入完成輸入SetGoodsID填寫訂單明細輸入商品數量數值輸入完成輸入SetGoodsAmount保存訂單用戶命令激活Save保存訂單打印訂單用戶命令激活Print打印訂貨單取消訂單用戶命令激活Cancel取消訂單9.5.1順序圖的映射4)方法的實現細節(jié)最后再討論一下順序圖所呈現出來的方法的實現細節(jié)問題,注意到圖中每一個對象的生命線上都從上到下排列了若干個被稱為“控制焦點”的小矩形。動態(tài)地看這些“控制焦點”,它們表示了對象在某個時間片段所處的狀態(tài)。而靜態(tài)地看這些“控制焦點”時,它們則在某種意義上直觀地描述了對應消息(方法)的處理邏輯。同時,順序圖中使用的組合片段也描述了各消息之間的順序、選擇、循環(huán)甚至并發(fā)等方面的約束。為方法的實現提供了明確且無二義性的支持。9.5.1順序圖的映射顯然,這個處理邏輯對程序員編程具有非常直接的意義,把這個過程寫成程序代碼并不困難。另外,任何一個模型都不可能代表目標系統(tǒng)的最終實現。模型中總有可能會忽略某些較小粒度的技術細節(jié)。對于順序圖來說,被忽略的就可能包括類、屬性、方法、約束條件等多個技術層面的東西,只要丟掉的細節(jié)不影響模型要表達的東西就可以了。例如圖9-9中的順序圖就忽略了商品(Goods)對象,圖9-9中卻出現了GoodsID、GoodsName、price等商品對象的屬性,也出現了與商品有關的GetGoodsPrice(GoodsID)方法,卻忽略了商品(Goods)對象,但這并不影響整個模型所要描述的過程。9.5.1順序圖的映射圖9-10分析順序圖得到的屬性和方法9.5.1順序圖的映射實現時,可以把創(chuàng)建、使用和銷毀商品對象的過程封裝在GetGoodsPrice(GoodsID)方法的內部,這并不影響整個過程的實現。值得注意的是,順序圖即包含十分豐富的信息,同時也會忽略掉很多細節(jié)。因此將順序圖直接轉換成程序代碼幾乎是一個不可能的問題,或者說將一張順序圖轉換成程序代碼實際上也是一個偽命題。因此,順序圖到實現的映射將是一個十分內在的過程。9.5.1順序圖的映射對于通信圖來說,通信圖是一種與順序圖語義等價一種圖。所以,通信圖的映射與順序圖的映射的總體思路和基本方法也都是相同的。不同的是,通信圖中增加了對象之間的鏈接,直接給出了類之間應具有的關聯(lián)關系,而順序圖中則要分析對象之間的鏈接關系。反過來,順序圖中可以使用組合片段(CombinedFragments),用來描述不同的交互片段之間的順序、選擇、循環(huán)和并發(fā)等各種約束,這些約束為順序圖的映射提供了更多的實現細節(jié)。9.5.2狀態(tài)圖的映射與順序圖不同,狀態(tài)圖通常用于描述某個特定的對象在其生命期內(或參與某項活動時)所處的各個狀態(tài)及其變遷情況。由于狀態(tài)圖主要用于描述一個特定的對象,所以狀態(tài)圖建模的主要意義在于對這個特定對象的屬性和方法進行建模。狀態(tài)圖中最重要的兩種元素就是的狀態(tài)和遷移。狀態(tài)通??梢员硎緸閷ο蟮哪硞€屬性(如狀態(tài)變量)或對象所滿足的條件,與狀態(tài)相關聯(lián)的動作則可以映射為有一個或若干個程序語句描述的動作或對象的方法。遷移用于表示對象狀態(tài)的改變,通常是由某個事件觸發(fā)的。當事件發(fā)生時,對象會根據對事件處理的結果修改相應的屬性值,改變對象的狀態(tài)。9.5.2狀態(tài)圖的映射因此,遷移可以映射為對象中的事件及其對事件的響應,不同的程序設計環(huán)境提供了不同的事件處理機制,這使得事件的映射方法也不盡相同。例如,對于隊列這樣一種比較簡單的對象來說,其狀態(tài)通常被定義成:空(Empty)、滿(Full)和半滿(SemiFull)三種狀態(tài)。隊列對象的狀態(tài)圖通常可以描述成如圖9-11所示的狀態(tài)圖。由于隊列對象僅用于對外提供數據緩存服務,通常不需要具有自主的主動行為,所以,隊列對象狀態(tài)通常不需要關聯(lián)的動作。9.5.2狀態(tài)圖的映射圖9-11隊列類類圖及其狀態(tài)圖9.5.2狀態(tài)圖的映射隊列對象的三種狀態(tài)均可表示為隊列對象的兩個屬性front和rear之間的關系,所以,對象的狀態(tài)可以使用特定的條件來表示。如圖中出現的三個邏輯表達式就表示了三個狀態(tài)所滿足的條件。這張圖映射到C++程序時,所得到的就是用C++實現的一個隊列類的定義與實現。此時,狀態(tài)圖所起的作用僅僅是描述了對算法實現方面的約束。9.5.2狀態(tài)圖的映射例如,對于網絡銷售系統(tǒng)中的訂單狀態(tài)問題,我們首先將訂單在其生存期內的狀態(tài)劃分成初始、待支付、待發(fā)貨、待收貨、待確認、退貨、完成和取消等多個狀態(tài)。(1)初始狀態(tài):表示客戶新提交的訂單,需要審核商品的品種和數量等信息后才能進行銷售,審核不通過的訂單將被自動取消。(2)待支付:表示訂單已審核通過,需要在指定期限內進行支付,超過期限的訂單將被取消,用戶需要時可重新訂貨。9.5.2狀態(tài)圖的映射(3)待發(fā)貨:表示客戶已支付到第三方賬戶,正在組織發(fā)貨。(4)待收貨:表示貨物已經發(fā)出,客戶可以根據發(fā)貨信息跟蹤貨物的物流情況。(5)待確認:表示客戶已收到貨物,客戶可以在指定期限內確認收貨已完成最終支付或提出退貨請求。超出期限,訂單將自動轉入已完成狀態(tài)。9.5.2狀態(tài)圖的映射(6)退貨:表示客戶已提出退貨申請,并完成退貨處理的狀態(tài)。(7)完成:表示客戶完成貨物的簽收或完成退貨確認,訂單處于最終的完成狀態(tài)。(8)取消:表示審核未通過或逾期未支付的無效訂單。這張狀態(tài)圖直觀地描述了一個訂單對象的狀態(tài)及其變遷情況??梢赃M一步得到的是狀態(tài)圖為訂單對象帶來的模型增量。如表示訂單狀態(tài)的屬性和修改狀態(tài)的方法。圖9-12訂單對象的狀態(tài)圖實現時,可以添加表示訂單狀態(tài)的類型,再添加必要的屬性和操作。這樣可得到經過細化的訂單類。圖9-13訂單類類圖9.5.2狀態(tài)圖的映射其中,表示訂單狀態(tài)的枚舉類型可定義如下:typedefenum{initial,paying,delivering,receiving,returning,confirming,complished,canceled}OrderStatus;新添加的屬性包括:CDateVerifyDate,ReceivedDate,ConfirmedDate,ReturningDate;和OrderStatusorderstatus;等,它們分別表示訂單的狀態(tài)、審核日期、收貨日期、確認日期和完成日期等。9.5.2狀態(tài)圖的映射新添加的操作則包括:verify(審核)、cancel(取消)、pay(支付)、send(發(fā)貨)、receive(收貨)、confirm(確認)和back(退貨)等。這些新的屬性和操作進一步細化了訂單類的設計。需要說明的是,這個例子中給出的映射方法并不是唯一的,也不一定是最合理的。例如,設計模式中的狀態(tài)模式就提供了一個不同的表示狀態(tài)的解決方式。9.5.2狀態(tài)圖的映射與順序圖和通信圖不同的是,狀態(tài)圖是一個相對封閉的軟件模型,即它僅用于描述一個對象的狀態(tài)。因此,目前已經有建模軟件能夠實現狀態(tài)圖的自動映射了。只要你的狀態(tài)圖建模足夠完善或完備,使用這樣的自動轉換也將是十分有意義的。9.6小結UML模型到應用程序的映射實際上就是UML模型中的類模型到應用程序的映射。實際的軟件建模過程中,可以使用建模工具提供的正向工程功能實現這個映射。需要指出的是,目前的大多數建模軟件還不能自動映射類圖之外的UML模型,如狀態(tài)圖、活動圖、順序圖和通信圖等。但這些模型描述的內容卻也是可以通過它們對類圖的影響映射到應用程序中。最后一個問題是,本章僅討論了基于C++模型映射。對于其他一些程序設計語言(如java或C#)來說,情況可能會有一些細節(jié)方面的不同。第10章面向對象的軟件設計原則學習目標

理解和掌握軟件質量屬性的基本概念,理解軟件質量與開發(fā)效率之間關系

理解和掌握基本的面向對象設計原理

通過案例學習在軟件設計過程中貫徹面向對象設計原則的方法第10章面向對象的軟件設計原則不論是用什么樣的軟件開發(fā)方法,軟件質量和開發(fā)效率永遠都是開發(fā)人員追求的目標。而衡量軟件質量的指標又是多元化的,不同的參與者對軟件質量的要求往往又不是完全一致的,又是甚至是相互沖突和矛盾的。開發(fā)人員更注重軟件的開發(fā)效率和可維護性,用戶關心得更多的則是軟件的有效性、可靠性、可用性和運行效率。軟件開發(fā)過程中,如何均衡各方面的要求則成為一個無法回避的問題。本章將介紹常見的軟件質量屬性和基本的面向對象的軟件設計原則,并討論如何貫徹這些設計原則以設計高質量軟件的一般方法。10.1軟件質量屬性開發(fā)高質量的軟件是一項極具挑戰(zhàn)性的工作,其中最重要的原因就在于對軟件質量的認識,不同的人對于軟件質量的定義和理解都不盡相同,這使得軟件開發(fā)過程充滿變數,變化莫測。所謂軟件質量,是指軟件與明確地敘述的功能和性能需求、文檔中明確描述的開發(fā)標準以及任何專業(yè)開發(fā)的軟件產品都應該具有的隱含特征相一致的程度。10.1軟件質量屬性為了確定軟件質量是否滿足要求,必須弄清楚影響軟件質量的因素有哪些,以及在軟件設計中如何解決這些因素帶來的質量問題。影響軟件質量的因素有很多,很多因素不僅僅來自于軟件本身,它們還可能來自整個計算機系統(tǒng),有的甚至來源于系統(tǒng)的環(huán)境。例如,系統(tǒng)的響應時間就同時來源于系統(tǒng)的硬件和軟件;安全性則取決于系統(tǒng)的硬件、軟件、人員以及其他環(huán)境因素。有些質量因素是強制性的,如過程控制系統(tǒng)或其他技術系統(tǒng)中的響應時間。不滿足這樣的質量要求將會引起嚴重后果,也有些因素是非強制性的。例如系統(tǒng)屏幕的刷新時間,這樣的時間稍長一點不會引起系統(tǒng)的失效。10.1軟件質量屬性人們從軟件用途的視角出發(fā),將軟件的用途劃分成操作(operation)、修改(revision)和轉移(transition)等三個方面。它們的具體定義如下:1)操作(operation)是指軟件用戶對軟件的日常使用;2)修改(revision)是指對軟件的維護及擴充;3)轉移(transition)是指將軟件用于新的用途,如與其他系統(tǒng)相連接,或者將軟件移植到新的系統(tǒng)環(huán)境中。10.1軟件質量屬性表10-1列出了與軟件用途相關的這些質量屬性及其定義。表10-1與軟件用途相關的軟件質量屬性屬性分類軟件質量屬性軟件質量屬性定義操作(operation)完整性(integrity)系統(tǒng)在處理物理干擾、防止非法存取等方面的能力。正確性(correctness)系統(tǒng)中的錯誤數目??煽啃?reliability)平均故障間隔時間以及可用時間所占的比例??捎眯?usability)學習系統(tǒng)的容易程度,執(zhí)行日常任務的有效程度。有效性(efficiency)系統(tǒng)響應的快慢,使用資源的多少,計算的準確程度等。修改(revision)可維修性(maintainability)錯誤的定位和修復的難易程度??蓽y試性(testability)測試的難易程度。靈活性(flexibility)擴充新特性的難易程度。轉移(transition)可移植性(portability)將系統(tǒng)移植到其他硬件或軟件平臺的難易程度??芍赜眯?reusability)把部分軟件重用于其他系統(tǒng)的難易程度?;ゲ僮餍?interoperability)與其他系統(tǒng)協(xié)同工作的難易程度。10.1軟件質量屬性上面列出的這些質量屬性來源于美國空軍的McCall和Matsumto定義的質量屬性列表,除此之外,還存在很多其他標準的質量屬性列表。它們不僅列出的軟件質量屬性不盡相同,并且對一些具有相同名稱的質量屬性給出的定義或描述也不盡相同。需要強調的是,所有這些標準都不是完備的,實踐中可以將這些標準作為參考,而根據需求定義出與特定項目相適應的質量屬性列表。在需求分析過程中,人們可以分析非功能需求中的所有質量因素,衡量這些因素中的重要性,并將那些重要的質量因素寫入需求規(guī)格說明書中,作為軟件的質量屬性列表。從開發(fā)和使用的角度出發(fā),人們又給出了另一種定義軟件質量屬性的標準。表10-2列出了按照這個分類標準定義出來的軟件質量屬性列表。10.1軟件質量屬性表10-2不同視圖下的軟件質量屬性用戶視圖下的軟件質量屬性開發(fā)者視圖下的軟件質量屬性有效性(availability)可維護性(maintainability)效率(efficiency)可移植性(portability)靈活性(flexibility)可重用性(reusability)完整性(integrity)可測試性(testability)互操作性(interoperability)

可靠性(reliability)

健壯性(robustness)

可用性(usability)

10.1軟件質量屬性比較這兩張質量屬性列表,它們列出的質量屬性并不完全相同,后者多出了健壯性(robustness)和有效性(availability),但同時缺少了正確性(correctness)和可用性(usability),但它們對軟件質量屬性的描述在整體上應該是一致的或完全相同的,不同的地方僅僅體現它們給出的具體的質量屬性定義上的差異。10.1.1用戶視圖下的軟件質量屬性用戶視圖下的軟件質量屬性是指對用戶特別重要或用戶特別關心的質量屬性。良好的質量屬性可以有效地幫助用戶實現其業(yè)務目標、解決他們在生產和經營活動中存在的各種問題、提高他們的工作效率、降低運營成本、提高他們的運營效率以及易于使用等很多用戶需要的軟件特性。用戶視圖下的軟件質量屬性包括:有效性(availability)、效率(efficiency)、靈活性(flexibility)、完整性(integrity)、互操作性(interoperability)、可靠性(reliability)、健壯性(robustness)和可用性(usability)等。10.1.1用戶視圖下的軟件質量屬性用戶視圖下的軟件質量屬性是指對用戶特別重要或用戶特別關心的質量屬性。良好的質量屬性可以有效地幫助用戶實現其業(yè)務目標、解決他們在生產和經營活動中存在的各種問題、提高他們的工作效率、降低運營成本、提高他們的運營效率以及易于使用等很多用戶需要的軟件特性。用戶視圖下的軟件質量屬性包括:有效性(availability)、效率(efficiency)、靈活性(flexibility)、完整性(integrity)、互操作性(interoperability)、可靠性(reliability)、健壯性(robustness)和可用性(usability)等。10.1.1用戶視圖下的軟件質量屬性1.有效性(availability)有效性(availability)是指在預定的啟動時間中,系統(tǒng)真正可用并且完全運行時間所占時間的百分比。更準確地說,有效性等于系統(tǒng)的平均故障前時間(MTTF)與平均故障前時間與故障維修時間之和的比值。顯然,這個比值越高,系統(tǒng)的有效性就越好。2.效率(efficiency)效率是指系統(tǒng)的運行效率,主要指系統(tǒng)資源的使用效率,可用處理器、存儲空間或通信帶寬等資源的使用效率。當系統(tǒng)耗盡了所有可用資源,那么用戶遇到的將使系統(tǒng)性能嚴重下降,甚至會影響到系統(tǒng)的安全性。10.1.1用戶視圖下的軟件質量屬性3.靈活性(flexibility)和可擴充性和可擴展性等一樣,靈活性主要指在軟件中增加新的功能是所需要的工作量的大小。如果軟件開發(fā)者能夠預見到軟件的可擴展性,那么他們就可以選擇合適的開發(fā)方法來最大限度地增加系統(tǒng)的靈活性。在軟件開發(fā)過程中,選擇增量模型和迭代式開發(fā)方法將可能是一種能夠有效增加系統(tǒng)靈活性的方法。4.完整性(integrity)完整性也可以稱為系統(tǒng)的安全性,主要指系統(tǒng)在防止非法訪問系統(tǒng)功能、數據丟失、病毒入侵和非法數據進入等事件的發(fā)生方面的抵御能力。任何一個系統(tǒng),尤其是互聯(lián)網系統(tǒng),都應該具有良好的完整性。任何違背完整性事件的發(fā)生,都有可能對系統(tǒng)的一致性和信息安全構成巨大的威脅。10.1.1用戶視圖下的軟件質量屬性5.互操作性(interoperability)互操作性表示的是系統(tǒng)與其他系統(tǒng)交換數據和服務的難易程度。開發(fā)軟件時,開發(fā)人員必須弄清楚用戶對系統(tǒng)在互操作方面存在的現實或潛在的需求,以便實現或在將來擴充需要的互操作功能。6.可靠性(reliability)可靠性一般被定義成系統(tǒng)無故障工作一段時間的概率。健壯性和有效性有時可以被看成可靠性的一個部分。衡量一個軟件的可靠性,可使用計算正確執(zhí)行的操作所占的比例、統(tǒng)計平均故障前執(zhí)行時間、和統(tǒng)計缺陷出現的密度等多種不同的方法加以實現。10.1.1用戶視圖下的軟件質量屬性7.健壯性(robustness)健壯性是指當系統(tǒng)及其組件遇到非法輸入數據、相關軟件或硬件組成部分的缺陷或異常操作等情況時,系統(tǒng)能夠繼續(xù)正常執(zhí)行的程度。具有良好健壯性的軟件應該能夠容忍用戶的不當操作等引起的錯誤,也可以從發(fā)生了各種異常的情形中將系統(tǒng)恢復到某個具有一致性的狀態(tài)。8.可用性(usability)可用性也被稱為是易用性,它通常包含了多個用戶友好方面的特性。可用性首先應包括的是用戶與系統(tǒng)交互方面應呈現出來的特性,如系統(tǒng)在準備輸入、操作和理解輸出方面應具有的特性??捎眯赃€應包括用戶在學習使用產品方面的應呈現出來的特性。10.1.1用戶視圖下的軟件質量屬性滿足這些質量屬性要求的軟件或系統(tǒng),可以保證用戶能夠容易、有效、安全、高效率地使用相應的軟件產品,幫助他們完成特定的工作,實現他們的工作目標。對于任何一種軟件產品來說,所有這些質量因素都是必須滿足

溫馨提示

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

評論

0/150

提交評論