軟件工程與開發(fā)技術(西電第二版)第7章面向對象技術總論
《軟件工程與開發(fā)技術(西電第二版)第7章面向對象技術總論》由會員分享,可在線閱讀,更多相關《軟件工程與開發(fā)技術(西電第二版)第7章面向對象技術總論(179頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、7.1概述-面向對象方法論 7.2面向對象技術的基本概念 7.3面向對象技術的基本特點 7.4面向對象分析方法 7.5面向對象技術與程序結構 7.6面向對象軟件工程 7.7設計模式(Design Pattern)與框架(framework) 7.8基于構件的軟件體系結構(com/dcom, corba,internet) 7.9 面向對象分析解決(描述)問題的模式,第7章 面向對象技術總論,7.1 概述面向對象方法論面向對象技術的內(nèi)容包括面向對象系統(tǒng)分析技術、系統(tǒng)設計技術、程序設計技術、測試技術以及各種基于面向對象技術的體系結構、框架、組件、中間件等。面向對象技術的基礎是面向對象程序設計,后者
2、是程序結構化發(fā)展的必然產(chǎn)物。眾所周知,高級程序設計語言經(jīng)歷了非結構化、結構化、面向對象三個發(fā)展階段,這三個階段的進化都是針對程序的結構和系統(tǒng)分析方法而做出的。程序的結構是指程序代碼之間的關系。每到一個新的階段,程序的結構就更加完善、更加復雜,代碼也更容易重用,抽象程度也更高。,軟件系統(tǒng)分析方法研究將問題域(現(xiàn)實世界)向求解域(程序域)轉換和映射的方法,其目的是把問題域(現(xiàn)實世界)中的概念或者處理過程轉換或映射成程序的元素和算法。問題域(現(xiàn)實世界)相對來說是不變的或者變化較緩慢的,但系統(tǒng)分析方法卻根據(jù)程序設計方法的不同而改變,因此系統(tǒng)分析方法依賴于程序設計技術,依賴于程序設計元素,參見圖7.1。
3、結構化分析方法和面向對象分析方法則又分別依賴于結構化程序設計語言和面向對象程序設計語言。,,圖7.1 系統(tǒng)分析方法對程序設計技術的依賴性,非結構化分析方法就是要把問題域或現(xiàn)實世界中的概念和處理,如員工工資、計算工資等轉換成變量定義和對變量進行處理的語句,其基本元素是變量和語句,即所謂的數(shù)據(jù)結構+算法。由于當時程序規(guī)模普遍比較小,運行和應用環(huán)境也比較單一,因此不太考慮程序結構或者軟件結構問題。整體來說,非結構化技術是重視算法輕視結構的一種方法。,,結構化技術的基本元素是定義良好的程序結構元素,如子程序(函數(shù))結構和單入口/單出口的控制結構。前者是程序的靜態(tài)結構,后者則是程序的動態(tài)結構。子程序結構
4、構成了整個程序的靜態(tài)結構,是動態(tài)控制結構的基礎(嚴格地說,每個語句都可以看成是對函數(shù)的調(diào)用)。結構化分析方法就是要把問題域(現(xiàn)實世界)中的問題(概念、處理)轉換成程序中的數(shù)據(jù)結構和子程序(函數(shù))。在這類方法中,可以認為:程序=數(shù)據(jù)結構+函數(shù)結構+函數(shù)調(diào)用。相應的數(shù)據(jù)流分析方法則將現(xiàn)實世界或者問題域中的業(yè)務處理轉換為程序的函數(shù)結構,這個過程稱為分析過程,將系統(tǒng)的結構變成更適合于程序域的形式,比如說具有重用、高效、穩(wěn)定等特征的結構,則是設計過程。,到了面向對象技術階段,程序的基本元素是數(shù)據(jù)結構和函數(shù)結構的統(tǒng)一體“類”。類是程序中的靜態(tài)元素,而動態(tài)元素是對象和消息。面向對象方法認為:程序=類結構+對
5、象+消息。面向對象分析的任務則是把現(xiàn)實世界中的概念或者處理都轉換為程序域中的類和方法,將現(xiàn)實世界中的過程轉換為對象之間的交互過程。面向對象設計使這種類和對象交互更加適合于計算機系統(tǒng)實現(xiàn),更加合理和高效,更加容易重用。例如將員工、工資都轉換成求解域中的類,計算某位員工工資的過程稱為向該員工對象發(fā)消息。,,如上所述,新一代的程序設計語言技術并不是簡單地否定上一代語言,而是在上一代語言的基礎上增加新的程序結構元素(函數(shù)、類),從而實現(xiàn)更復雜的程序結構。這種新的程序元素更直觀、更真實、更自然、更完整地抽象了現(xiàn)實世界中的數(shù)據(jù)和處理(或者事物與概念),更好地抽象了程序中的變量和代碼,也進一步增強了程序的易
6、讀性、安全性、穩(wěn)定性和重用性,同時改變了系統(tǒng)的分析和設計方法。歸根結底,程序設計語言的發(fā)展就是程序結構以及建立在其基礎上的分析、設計方法的發(fā)展。,,上面的例子表明,實現(xiàn)同樣的功能可以采用不同的程序元素、程序結構或者程序設計技術。高級的程序設計方法更擅長解決復雜的問題,因為其程序元素和程序結構更為復雜。這實際上是自然界和社會系統(tǒng)的一個普遍規(guī)律,即內(nèi)部結構決定外部功能。如果把系統(tǒng)解決的問題比做該系統(tǒng)實現(xiàn)的外部功能,而把實現(xiàn)這些功能的程序元素及其關系看做是內(nèi)部結構,越復雜的內(nèi)部結構就預示著系統(tǒng)的功能越復雜、越強大,比如說,人的大腦結構要比動物的大腦結構復雜得多,因此其功能也要強大得多。,,面向對象的
7、程序結構要比面向過程的程序結構更復雜,因此可以實現(xiàn)的功能也就更加強大。程序設計語言技術的發(fā)展歷史充分證明了客觀和主觀系統(tǒng)進化中,功能和結構之間關系的一般規(guī)律。圖7.2表現(xiàn)了系統(tǒng)外部功能和內(nèi)部結構之間的關系,其內(nèi)部結構也是分層次的,這也符合了人認識世界的一般規(guī)律:由外向內(nèi)、由表及里。,,圖7.2 軟件系統(tǒng)外部功能和內(nèi)部結構之間的關系,圖7.3 軟件系統(tǒng)外部功能和內(nèi)部結構關系的例子,,7.2 面向對象技術的基本概念7.2.1 類對象是指現(xiàn)實世界或者概念世界中的任何事物,類是具有相同結構特征的對象的結構抽象。此結構特征包括對象的屬性特征和操作接口特征。屬性特征定義了所有對象都具有的屬性名稱及類型;操
8、作接口特征則定義了所有對象都具有的操作和方法。,,面向對象程序語言中的類是一個代碼的預定義模塊或者程序結構元素,類似于函數(shù)、結構體或者記錄類型定義,其中包含了相關的變量和函數(shù)定義。類中的變量稱為屬性或者成員變量;類中的函數(shù)稱為成員函數(shù)(操作和方法)。操作和方法的區(qū)別在于:操作強調(diào)其操作接口,方法則強調(diào)實現(xiàn)方式和算法??梢园熏F(xiàn)實世界中的對象映射為程序語言中的類,有時候這種映射比較困難且不明顯,則可在其間增加一個概念世界或者概念模型。這種映射的過程即為面向對象的系統(tǒng)分析,如圖7.4所示。,,圖7.4 現(xiàn)實世界向計算機世界的轉換,現(xiàn)實世界中的對象一定能夠抽象成類,但程序語言中的類則不一定有現(xiàn)實世界原
9、型。這種不對稱性反映了信息系統(tǒng)的特殊性,即程序模型并不一定是現(xiàn)實世界的原始或者簡單的等價。因為現(xiàn)實世界中的任何事物都可以被抽象為類,因此可以把面向對象看成是一種世界觀和方法論,在這種世界觀和方法論基礎上,現(xiàn)實世界被轉換成程序世界就顯得比較自然。例如:企業(yè)中的員工、倉庫、庫存帳目、商品及類別、物體、力等。,,在程序設計語言中,類是一個完整的、獨立的、可重用的,具有低耦合、高內(nèi)聚特性的程序模塊。類相當于一種自定義數(shù)據(jù)類型,它類似于C語言中的結構體類型(C++本身就可以使用strut關鍵字來定義類),不僅包含數(shù)據(jù)結構也包含操作結構。數(shù)據(jù)類型作為程序語言中進行變量內(nèi)存分配、類型匹配、操作檢查的基礎,為
10、程序的一致性和安全性提供了重要的保證。因此,類概念的引入從類型角度進一步提高了程序的安全性。,,7.2.2 對象及對象實例現(xiàn)實世界中的具體事物就是對象或者對象實例,類則是對象實例的結構抽象。每個對象實例一般具有三方面的特性(亦稱對象“三要素”):(1) 確定的標識,能夠被唯一地確認。(2) 具有一定的屬性,表示其性質(zhì)或狀態(tài)。(3) 具有一定的行為能力或者操作能力,可給外界提供服務或者通過操作改變其狀態(tài)。,,對象標識也是對象屬性之一,是一類特殊的屬性,類似于實體關系模型中的主碼。應當注意,對象標識和對象在程序中的標識是不一樣的,前者是對象本身的固有屬性,后者是在程序空間中給該對象起的名字,僅供程
11、序中使用。現(xiàn)實世界中的任何事物都可以抽象成對象,例如具有具體物質(zhì)形態(tài)的對象,如員工、計算機、汽車等;具有抽象物質(zhì)形態(tài)的對象,如銀行賬戶、力等。,,面向對象本身就是一種世界觀以及由此派生的方法論,是一種觀察世界和認識世界的方式。在面向對象的世界觀中,世界是由對象及其關系組成的,對象是由屬性和行為組成的,對象之間具有各種各樣的聯(lián)系。類是對象結構的抽象,關系是對象之間聯(lián)系的抽象。對象世界的發(fā)展變化過程就是對象之間的交互過程(面向過程也是一種世界觀,認為世界是由過程組成的,每個過程都有自己的目標和處理的對象)。面向對象的世界觀中的屬性和操作剛好對應了程序世界中保存數(shù)據(jù)或者狀態(tài)的變量和實現(xiàn)一定功能的函數(shù)
12、。屬性是事物的性質(zhì)和狀態(tài)描述;行為是對屬性的操作,可以對外提供服務,屬性則是行為的基礎和操作的內(nèi)容。,,根據(jù)屬性和行為的側重點不同,對象又可以分成實體對象和過程對象,前者強調(diào)對象的狀態(tài)描述,例如“學生”對象;后者強調(diào)對象的過程特性,例如“流程”對象?,F(xiàn)實世界中的事物都是有聯(lián)系的,對象之間也有聯(lián)系。例如對象間的組成關系:如汽車對象是由零件對象組成的;關聯(lián)關系(信息聯(lián)系):如老板有員工的聯(lián)系方式。對象之間有些聯(lián)系是暫時的:如某人向你問了一下路(發(fā)送消息),你向其提供了服務;有些聯(lián)系則是永恒的、持久的:如父母、子女之間的關系;有些則是介于兩者之間的:如配偶關系等。,,從靜態(tài)角度來看,對象實際上就是由
13、類(包括數(shù)據(jù)結構和函數(shù)結構定義)模板派生的變量;從動態(tài)角度來看,對象之間的交互(包括自交互)完成或者實現(xiàn)了功能。在面向對象程序中,類是一種代碼模板定義,它類似于函數(shù)結構和數(shù)據(jù)結構,必須要實例化才能使用。實例化就是使用類創(chuàng)建具體的對象變量(也叫對象實例),由類產(chǎn)生對象變量相當于在工廠中使用模具生產(chǎn)產(chǎn)品。在程序中只有創(chuàng)建了具體的對象變量,系統(tǒng)才會給其分配內(nèi)存,程序才能訪問其屬性和操作。,,由于對象變量占用的內(nèi)存空間不固定,其內(nèi)存分配方式多采用動態(tài)分配和回收機制。在面向對象程序設計語言中,除了對象變量本身,還有一種引用變量(reference variable),其本質(zhì)上是指針或者地址,可以指向對象
14、變量,其類型必須是一致的。通過引用變量訪問對象變量簡化了對動態(tài)分配的對象內(nèi)存空間的訪問。如Student是Java語言中定義的類,語句Student s = new Student();聲明了一個引用變量s,創(chuàng)建了一個對象變量new Student(),并通過賦值語句將該對象變量所在的內(nèi)存區(qū)域的首地址存放到s中,通過s可以對此內(nèi)存區(qū)域進行操作。一般來說,引用變量和對象變量是在不同的內(nèi)存空間中,前者存放在堆棧空間中,后者是放在堆空間中,這兩種內(nèi)存空間所允許的操作是有所不同的(如圖7.5所示)。,,圖7.5 引用變量和對象變量之間的關系,7.2.3 消息機制純面向對象程序設計語言如Java中,所有
15、的函數(shù)或者操作都依附于一個對象主體,這種依附于某個對象的函數(shù)叫做成員函數(shù)或者對象操作(方法)。在純面向對象程序中,對任何一個函數(shù)的調(diào)用都是對某個對象的方法調(diào)用,同時會把該對象的信息(一般是內(nèi)存地址)傳遞給被調(diào)用函數(shù),這就是函數(shù)的實例化過程。在面向對象程序中,調(diào)用一個對象的方法或者操作叫做向該對象發(fā)消息,調(diào)用者叫做消息發(fā)出者,被調(diào)用者叫做消息接受者。消息、事件和函數(shù)調(diào)用或者事件響應是相輔相承的。程序中,消息就是現(xiàn)實世界中的請求或者通知事件,這一般都是通過對系統(tǒng)執(zhí)行一定的操作完成的。對該請求或者通知可以響應,也可以不響應,響應可以是同步的,也可以是異步的。,例如,客戶如果想從ATM機中取錢,通常會
16、按下取錢按鍵,這實際上就是向ATM機發(fā)送了取錢消息,也是向ATM機發(fā)送了取錢請求,ATM機會顯示一個取錢界面,讓用戶輸入取款數(shù)額,這是通過ATM機的一個方法或者操作實現(xiàn)的。用戶輸入取款金額后按下確定鍵,相當于又向ATM機發(fā)送新的消息,導致ATM機的另一個方法的調(diào)用,通常在該方法中又會向其他對象發(fā)送消息,例如該客戶的賬戶Account對象,通過調(diào)用該賬戶對象的draw()操作實現(xiàn)賬戶上資金的更新。用戶通過和ATM機一系列的請求/響應的交互活動完成了執(zhí)行系統(tǒng)的某個功能,如取錢。客戶對象、ATM對象、Account對象之間的消息交互見圖7.6。,,圖7.6 消息機制,,7.3 面向對象技術的基本特點
17、7.3.1 封裝性程序的基本元素是變量定義以及對變量的處理。對于規(guī)模比較小的程序,每個變量的意義和訪問都由程序員自己控制,但對于需要多人長時間開發(fā)的大規(guī)模程序,存在訪問其他人定義的變量的情況,這時候變量的安全性則成為問題。程序中有很多錯誤都是由于錯誤地訪問了不該訪問的變量而引起的。面向過程程序設計語言中的函數(shù)結構中的局部變量在一定程度上解決了這個問題,但是全局數(shù)據(jù)結構或者變量中還是存在不安全的訪問問題。面向對象程序將存儲數(shù)據(jù)的變量和對數(shù)據(jù)(變量)的處理(方法)封裝起來(私有化),從程序外部不能直接訪問數(shù)據(jù),而必須通過對外公開的方法進行訪問,這就避免了對正確數(shù)據(jù)的錯誤操作,如圖7.7所示。,,圖
18、7.7 對象的封裝性,將Account對象中表示余額的屬性balance(實型變量)隱藏起來,對外部程序不可見,外部程序只能通過公開的方法save ( )或者draw ( )來改變balance的值,這樣就可以避免外部程序對其進行錯誤的操作。比如說:在程序中直接對balance變量做乘除法操作(例如實現(xiàn)存錢操作時將“+”敲成“*”號),而編譯程序是沒有辦法發(fā)現(xiàn)此錯誤的,因為對于實型變量來說,不能限制對其做乘除操作,從語法上來看這些都是合法的操作。對于賬戶余額來說,乘除法則是無意義的操作。因此可以通過隱藏數(shù)據(jù),公開合法的操作接口來限定賬戶這種對象的內(nèi)涵和外延,增加程序的安全性。,,面向對象的封裝
19、性實現(xiàn)的是信息隱藏。僅將需要向外公開的方法和屬性向外公開;所有不需要向外公開的方法和屬性都被隱藏起來。正像電視機一樣,內(nèi)部電路元件對用戶都隱藏起來,對外只公開用戶可用的接口,如開關、音量調(diào)節(jié)、調(diào)臺等。這種封裝性通過定義合適的操作接口來進一步確定事物的本質(zhì)特征。對于傳統(tǒng)的面向過程的程序設計語言來說,表示銀行存款和圖形尺寸時都是使用實型變量,沒有區(qū)別,但實際上對這兩種量的操作是有區(qū)別的。很明顯,銀行存款只允許增加、減少或者查詢;對尺寸來說卻能按比例放大或者縮小,即執(zhí)行乘除法。類似的還有數(shù)據(jù)結構中的例子,保存線性表、堆棧、隊列元素的數(shù)據(jù)存儲結構可以是一樣的,但對其允許的操作是不一樣的。封裝性增強了程
20、序中變量的安全性,同時也增強了程序中數(shù)據(jù)類型、數(shù)據(jù)結構和變量的語義內(nèi)涵,提高了程序分析方法的直觀性。,7.3.2 繼承性軟件重用技術始終是軟件開發(fā)技術研究中的一個重要課題,從程序行的簡單復制到宏替換,從數(shù)據(jù)結構定義再到函數(shù)定義,從類的定義到類的繼承,從構件到框架等,都是代碼重用技術的體現(xiàn)。繼承機制是一種高級的代碼重用技術,子類自動繼承父類的所有代碼并且可以進行任意的覆蓋和擴充。如圖7.8所示,子類研究生繼承了父類學生中的屬性和操作,又擴充了新的屬性和操作。子類和父類保持一種動態(tài)關系:當父類代碼改變的時候,子類繼承的那部分代碼會自動修改,即子類對父類的繼承不是簡單的復制,而是動態(tài)的鏈接,子類和父
21、類始終保持一種聯(lián)系,這是一種與生俱來的、靜態(tài)的聯(lián)系,一旦定義,則無法改變。,,子類對父類的擴充包括對父類同名屬性和方法的覆蓋以及增加新的屬性和方法。過多的繼承層次會使程序結構變得異常復雜、難以理解并且難以維護。子類不僅僅繼承了父類的代碼,也繼承了父類的類型,或者說和父類型是相容的。程序設計語言中的繼承關系區(qū)別于生物界中的遺傳關系,如父子關系,更像事物分類中的分類關系。父類往往是各子類的共性的抽象,是對所有子類對象的抽象。例如:汽車、自行車、三輪車的父類是車,車是一個抽象的概念,凡是具有輪子可以滾動行走的物體都可以稱為車。又比如三角形、矩形、圓等具體圖形的父類可以定義為圖形類等。圖7.8中,研究
22、生屬于學生中的一種,是特殊的學生,因此是從一般到特殊的分類關系。,圖7.8 類的繼承關系,7.3.3 多態(tài)性多態(tài)性(polymorphism)是指同一種事物可以有多種不同的形態(tài)或者含義,也可以認為是從不同的角度觀察同一事物,可以得到不同的視圖。在面向對象程序設計語言中,多態(tài)性有三種含義。多態(tài)的第一種含義是方法的重載(Overload),在同一個類中可以存在同名不同參數(shù)的操作,這些操作的具體實現(xiàn)是不同的,即同名方法在不同的參數(shù)情況下有不同的實現(xiàn)。這反映了客觀世界中對事物操作的復雜性和聯(lián)系性,如對銀行來說,存錢是一種操作,但根據(jù)用戶出示的是存折還是銀行卡,其具體的實現(xiàn)有所不同。編譯程序通過參數(shù)類型
23、或者個數(shù)來確定具體調(diào)用哪個方法,因為這種多態(tài)性是在編譯階段完成的,所以可以稱為靜態(tài)的多態(tài)性或者編譯期多態(tài)性。操作符重載也是基于這種多態(tài)性的。例如圓對象可以根據(jù)不同的初始條件進行構造,見下面代碼。,class Circle public Circle(double x,double y,double r) //已知圓心坐標和半徑 public Circle(Point center,double r) //已知圓心和半徑 public Circle(double x1,double y1,double x2,double y2,double x3,double y3)//已知圓上三點坐標 pu
24、blic Circle(Point p1,Point p2,Point p3) //已知圓上三點 public Circle(Point p1,Point p2,double r) //已知圓上兩點和半徑 ,,下面是引用上述定義創(chuàng)建圓對象的代碼:Circle c1 = new Circle(); //創(chuàng)建一個默認的圓對象Circle c2 = new Circle(new Point(2,2),5); //創(chuàng)建已知圓心和半徑的圓對象Circle c3 = new Cirlce(0,0,2,3,4,5); //創(chuàng)建已知圓上三點坐標的圓上述代碼中同名方法具有不同的參數(shù),給出了在不同初始條件下構建
25、圓對象的方法。,,多態(tài)的第二種含義是子類對父類的方法進行覆蓋(override),程序會根據(jù)當前對象狀態(tài)而自動調(diào)用父類或者子類對象的方法。這一點和下面講的多態(tài)性的第三種含義本質(zhì)上是相同的。這種多態(tài)性由于在運行期間才能確定,因此稱為動態(tài)的多態(tài)性或者運行期多態(tài)性。,,例如:Shape是圖形類,Circle是其子類,父類和子類的方法getArea()具有不同的實現(xiàn)。public class Shape double getArea()return 0.0;public class Circle extends Shape double r; double getArea()return Math.P
26、I * r * r;,,上面類的對象實例創(chuàng)建代碼Shape s = new Circle()將子類對象實例賦值給父類的引用變量(這一點正是類型的多態(tài)性,本節(jié)后面詳細解釋),那么s.getArea()方法將調(diào)用父類還是子類的方法呢?按照類型分析,s是Shape類型,則s.getArea()方法應該是Shape的方法,但是s實際上指向的是Circle對象,所以s.getArea()方法應該是Circle的方法,但這是在運行期間才能確定的,因為s具體指向的對象只有在運行期才能確定。不同的語言在此處有不同的處理方法。在C++中,上述代碼調(diào)用的是Shape的getArea()方法,但是如果在Shape的
27、getArea方法定義前面加上virtual關鍵字,即:virtual public double getArea();,,則同樣的代碼s.getArea()調(diào)用的方法是子類Circle的方法。方法定義前面加上virtual的意思是指該方法的具體執(zhí)行代碼直到運行期才能確定。在Java中,對象的方法默認都是運行期確定的,因此s.getArea()一定是調(diào)用s實際指向的對象的方法,即Circle對象的方法。如果要想調(diào)用父類的area()方法,只需要讓s指向父類對象即可:Shape s = new Shape();這種運行期確定方法的執(zhí)行代碼正如運行期分配或者刪除對象空間一樣,是非常靈活高效的,所以
28、Java取其作為語言的默認特性,這也是Java語言簡潔高效且能迅速普及的原因之一。,,多態(tài)的第三種含義是類型的多態(tài)或者類型造型(type cast),前者是指一個對象可以看成是多種類型,后者是指子類對象可以造型成父類型,即將子類對象看成是父類類型,類似于類型強制,注意只是“看成”是父類類型,而不是真正的父類對象,子類對象永遠不能變成父類對象,而只能扮演成父類對象,以通過程序語法的類型匹配檢查,但其本質(zhì)上還是子類對象。這在生活實際中也是經(jīng)常遇到的,例如一個研究生去應聘,如果企業(yè)只招聘本科生的話,他也可以將自己看成是本科生而降級使用,但他自己本質(zhì)上還是研究生。除了子類對象可以扮演(造型)成父類類型
29、外,某個類的對象也可以造型成該類實現(xiàn)的接口類型。,,造型的方法就是將該類對象賦值給某種類型的引用變量,如:A obj = new B(),B要么實現(xiàn)A接口,要么B是A的子類。定義引用變量并沒有創(chuàng)建對象,相當于定義了一種類型約束。在面向對象語言中,這種造型稱為向上造型(upcast),它是安全的,因為子類型肯定滿足父類型的要求,子類型要么等于父類型,要么大于父類型(擴充)。從類的現(xiàn)實世界語義來看,子類和父類的關系是ISA(讀作“是一個”)關系,即子類對象首先是一個父類。圖7.9中的關系讀作研究生是一個學生,這無疑是客觀正確和可理解的。從哲學概念上來看,子類和父類正反映了特殊和一般、個性和共性的關
30、系,一般性寓于特殊性之中,共性寓于個性之中。這是面向對象技術中繼承或者接口概念的本質(zhì),這也是只有具有繼承或者實現(xiàn)接口關系的對象才能造型的原因。,,圖7.9 ISA關系,數(shù)據(jù)類型在程序設計語言中的重要性毋庸置疑,它是內(nèi)存分配、類型檢查、操作檢查的基礎。程序語言中數(shù)據(jù)類型的多少是衡量該語言功能是否強大的依據(jù)之一,現(xiàn)在的程序語言都提供了大量標準數(shù)據(jù)類型以及自定義數(shù)據(jù)類型的機制。在面向對象程序設計語言中,類可以看成是一種自定義類型。類型檢查也是程序安全性檢查機制之一,通過檢查相關操作的類型匹配可以發(fā)現(xiàn)很多不兼容的錯誤。比如:賦值操作、各種運算操作,如果沒有類型檢查的話,將會出現(xiàn)很多程序員難以察覺的錯誤
31、,這也是過去類型檢查機制較弱的弱類型語言(如C語言)容易出錯的原因。,,面向對象機制中類的定義實際上增強了類型檢查的安全性,一個類就相當于一種自定義的數(shù)據(jù)類型,不同類定義的變量是不允許相互賦值的,這雖然增強了程序的安全性,但卻帶來了另外一個問題,那就是代碼效率很低,針對每一個事物都需要定義一個類,例如定義堆棧類就得針對不同的元素類型定義多個類,每個類只能接收一種類型元素。C++采用一種叫做模板(template)的機制來處理這個問題,而Java則采用多態(tài)性來解決這個問題。多態(tài)(polymorphism)的原意就是同一個事物可以具有多種狀態(tài),或者說同一個事物在不同的場合、從不同的角度可以看成是不
32、同的東西,這是客觀事物復雜性的程序表現(xiàn)。,,7.3.4 抽象性抽象是人類思維的本質(zhì)特性之一。抽象性是對復雜事物本質(zhì)和特性的提煉和概括的能力,可以說沒有抽象就沒有理論思維,就沒有指導認識世界改造世界的一般性結論,也就沒有系統(tǒng)分析和設計。在程序中始終存在著抽象性,數(shù)據(jù)類型是數(shù)據(jù)結構和操作接口的抽象,常量是程序中常數(shù)的抽象,變量是程序中變化的數(shù)據(jù)的抽象,函數(shù)是實現(xiàn)某個功能或者處理代碼的抽象,類是多個實例對象結構(屬性和操作接口)共性的抽象,抽象類或者接口又是多個類公共接口的抽象。,,面向對象技術將抽象性引入到代碼的實現(xiàn)中,可以實現(xiàn)很多更抽象、更一般、更統(tǒng)一的方法。比如說:Shape是所有圖形對象的父
33、類,是抽象的,則方法getArea(Shape s)可以返回任何圖形的面積,totalArea(Shape s)則可以返回任意多個任意圖形的面積和,draw(Shapes)則可以畫出任意多個任意圖形。注意:這些方法本身都具有抽象性、一般性的含義。當然,這些抽象的方法并沒有真正去實現(xiàn)計算每個具體圖形的面積或者畫出具體的圖形,而只是完成通用的操作,如對所有的圖形進行求和或者畫出所有的圖形(兩者都是對集合進行遍歷),而把具體的操作都交給具體的子類(如圓、矩形)來實現(xiàn)。在面向對象程序設計語言中,抽象類、接口或者模板類都很好地實現(xiàn)了抽象的功能。,,由于程序中引入了抽象的操作,因此使得程序結構出現(xiàn)依賴倒置
34、的現(xiàn)象。過去結構化分析方法得到的系統(tǒng)結構是自上而下、逐步求精,上層抽象的模塊依賴于下層具體的模塊,上層模塊通過調(diào)用下層模塊完成任務,或者說先有下層模塊,才有上層模塊。面向對象程序的繼承結構中則是下層依賴于上層,因為上層是父類,下層是子類,先有上層再有下層,因此程序變得更抽象。程序結構依賴性對比如圖7.10所示,左邊部分的每個矩形框是函數(shù),右邊部分的每個矩形框是類。,,圖7.10 頂層模塊和底層模塊之間的依賴關系,,7.4 面向對象分析方法系統(tǒng)分析方法就是把現(xiàn)實世界或者問題域中的概念和過程轉換成求解域或程序域中元素的方法。因此系統(tǒng)分析方法是和程序域元素密切相關的。結構化或者面向過程的分析方法是把
35、現(xiàn)實世界或者問題域中的過程處理抽象成概念模型中的數(shù)據(jù)輸入、數(shù)據(jù)處理和結果輸出,然后將處理過程轉換成程序結構中的函數(shù)。程序中的函數(shù)有些是直接來自于現(xiàn)實世界中的處理過程,如計算工資,但僅靠現(xiàn)實世界中的處理過程是不夠的,在程序中還有很多處理過程是和計算機或者程序本身密切相關的,如輸入數(shù)據(jù)的過程等。,,面向對象的分析方法就是把現(xiàn)實世界或者問題域中的事物、概念、過程等抽象成概念模型中的對象或類,然后轉換成程序語言中的對象或類。程序語言中的類概念本身也來自于現(xiàn)實世界中的對象,因此概念模型中的類和程序語言中的類是一致的。但是僅靠現(xiàn)實世界中的類是不夠的,作為信息系統(tǒng)或者程序模型,本身也有自己獨特的機制和規(guī)律,
36、具有區(qū)別于現(xiàn)實世界或者問題域的特點,例如每個程序都具有一定的運行環(huán)境和操作界面等,這些因素也被抽象為系統(tǒng)中的類,視為系統(tǒng)類?,F(xiàn)實世界中抽取的類一般稱為業(yè)務類或者領域類,即在現(xiàn)實世界中存在有原型的類。業(yè)務類又可以分為分析類和設計類,前者是從現(xiàn)實世界中直接抽取的類,后者是對分析類的抽象、包裝、組合、擴充和修飾,如設計模式中的一些父類、實用類等。,按照目前廣泛流行的MVC模式,現(xiàn)實世界中的類相當于模型類(Model),確定了現(xiàn)實世界事物本身的邏輯、聯(lián)系和規(guī)律等,如學生、職工、工資、力等。其他的類,如表現(xiàn)類(View),則是對模型數(shù)據(jù)的計算機表現(xiàn),是人機接口界面類;控制類(Control)則控制系統(tǒng)的
37、運行流程。,,從系統(tǒng)的頂層結構到系統(tǒng)的微觀結構中,MVC結構都是存在的,例如:Struts框架結構是系統(tǒng)的整體架構,是符合MVC模式的,而Java的圖形界面swing組件類本身也是按照MVC模式設計的。MVC模式實際上給出了構建信息系統(tǒng)的一種過程和方法:即從業(yè)務對象到系統(tǒng)對象,從業(yè)務模型到系統(tǒng)模型的演化過程。首先抽象現(xiàn)實世界中的相關對象,稱為業(yè)務對象,在此基礎上添加對其的表現(xiàn)類即視圖類,系統(tǒng)流程(宏觀)和業(yè)務流程(微觀)的控制則轉換成控制類。一般來說,業(yè)務類可以做到與實現(xiàn)環(huán)境或者實現(xiàn)語言無關,但界面類或者系統(tǒng)控制類則可能和實現(xiàn)環(huán)境及實現(xiàn)語言有關。從現(xiàn)實世界對象模型到系統(tǒng)對象模型的演化過程如圖7
38、.11所示,系統(tǒng)對象中最上層的是業(yè)務對象,第二層是控制對象,最底層是界面對象。,,圖7.11 現(xiàn)實世界的對象模型向程序世界的對象模型轉換舉例一,有些系統(tǒng)模型的類會更多一些,另一個現(xiàn)實世界模型向程序世界模型轉換的例子超市購物向網(wǎng)上購物網(wǎng)站的轉換,其中,業(yè)務模型包括產(chǎn)品(Product)、購物車(Cart)、訂單(Order)和客戶(User)四種;系統(tǒng)模型類包括產(chǎn)品(Product)、購物車(Cart)、訂單(Order)、訂單數(shù)據(jù)庫(DB Order)和客戶(User)五種。從業(yè)務世界模型向程序世界模型轉換的示意圖如圖7.12所示。,,圖7.12 現(xiàn)實世界的對象模型向程序世界的對象模型轉換舉例
39、二,,7.5 面向對象技術與程序結構7.5.1 概述程序對外提供的功能是其外部特性,內(nèi)部也有著自己獨特的結構,即程序結構。程序中具有完整語義的最小語法單位是表達式,語句是程序執(zhí)行的最小單位,語句的集合組成了程序。語句相當于原子,語句與語句之間的關系形成程序結構,如順序、選擇、循環(huán)。數(shù)據(jù)結構、函數(shù)定義也是一種程序結構,稱為程序模塊,它由完成某個特定功能的多條語句組成。模塊的類型包括數(shù)據(jù)模塊、算法模塊或者二者的綜合。程序模塊是作為一個整體存在的,可以獨立地開發(fā)存儲,具有獨立性、安全性、語義性和重用性。其中數(shù)據(jù)模塊類似于數(shù)據(jù)結構定義,比如C語言中的結構體;算法(程序)模塊類似于函數(shù)。數(shù)據(jù)和算法(程序
40、)的綜合就是面向對象程序中的類。,,在程序從非結構化到結構化再到面向對象的進化過程中,程序結構越來越復雜、越來越豐富、重用粒度越來越大、結構層次也越來越深,對外呈現(xiàn)的功能也越來越強大。其內(nèi)部結構和外在表現(xiàn)之間的關系符合自然界和社會進化的一般規(guī)律,即內(nèi)部結構越復雜,其對外呈現(xiàn)的功能也就越強大。但是,這種內(nèi)部結構必須是建立在一種優(yōu)化合理的基礎上,而不是簡單的堆積。目前的包類函數(shù)的層次結構就是一種公認的優(yōu)化合理結構。,,程序結構中包含靜態(tài)的結構和動態(tài)的結構。靜態(tài)的結構就是程序代碼之間的關系,如類的繼承、關聯(lián)關系等,是代碼定義階段的關系;動態(tài)結構是函數(shù)的調(diào)用或者向對象發(fā)消息的過程,是代碼執(zhí)行時的關系。
41、動態(tài)結構要以靜態(tài)結構為基礎。圖7.13和圖7.14分別表示了面向過程和面向對象程序之間的靜態(tài)結構關系和動態(tài)結構關系,從圖中可以看出,面向對象程序的結構要比面向過程程序的結構復雜得多。,,軟件工程的實踐證明,程序的結構是通過不斷的改進而得到優(yōu)化的,不會一步到位。好的程序結構可以通過有經(jīng)驗的開發(fā)人員在設計階段通過精心設計而得到,也可以通過對已有的結構中不太好的代碼進行不斷改進而得到。通過代碼改進程序結構的方法也稱為“重構”。由于重構是從質(zhì)量欠佳的代碼基礎進行改進的,而不是一下拿出高質(zhì)量的結構設計,因此這種方法更受初學者的歡迎,也越來越受到軟件界的重視,目前幾乎所有的主流開發(fā)環(huán)境都提供了對重構工具的
42、支持。,,圖7.13 結構的層次靜態(tài)結構,圖7.14 程序執(zhí)行的線索動態(tài)結構,7.5.2 重構重構(Refactor)是指在不改變代碼的外在功能的前提下重新設計已有代碼,以獲取代碼新的特性。這里新的特性主要就是由于結構的改進而帶來的高效性、安全性、穩(wěn)定性、可維護性和可擴充性等。根據(jù)上一小節(jié)中所描述的程序結構的改進過程可以看出,這種重構是完全可能的,也是很有必要的。根據(jù)外在功能和內(nèi)部結構的關系來看,重構的目的主要在于改進程序結構。需要注意的是,重構不是整體重新建造(Reconstructor),可能只是局部的修改(Refactor),如把一些代碼抽象成方法,以提高程序結構的粒度,增加重用度。甚至
43、可能只是非常簡單的重命名,以改善程序的可讀性等。重構對于那些沒有做充分的設計而直接編碼的軟件開發(fā)過程而言是非常有效的。,,常見的重構方法有:提取方法(Extract Method)、引入父類(Introduce Super Class)或者接口(Interface)、屬性和方法上移或者下移(Attribute or Method Move up or Move down)等。重構所影響的程序范圍可能很小或者很大,但是即使最小的變化也可能引入bug。一處修改可能導致整個代碼變化,所以重構后必須要測試所有可能受影響的地方,這樣才能保證對外的功能不會改變。,,重構的種類有很多,重構的工作量有時候也會
44、很大,尤其是當現(xiàn)存代碼比較多的時候。目前主流的開發(fā)環(huán)境如Eclipse、Microsoft Visual Studio 2005等,都提供自動進行重構的工具。當然,不同的語言和開發(fā)環(huán)境提供的重構工具種類會有所不同,下面列舉了一些常見的重構方法:(1) try/catch重構:將普通代碼塊置于try/catch塊中,將代碼的正常執(zhí)行過程和錯誤處理過程分離開來,可以增加代碼的安全性和魯棒性。,,(2) 重命名(Rename)和移動(Move):由于各種可能的原因,對現(xiàn)存代碼中的包、類、接口、方法、屬性或域變量、局部變量等進行重新命名,同時對所有相關的引用(reference)都作相應的修改。該重構
45、還包括移動類和包進行重構的方法。即將包或者類從現(xiàn)有的位置移到另外的包中,或把靜態(tài)成員從一個類中移到另外的類中。這些重構方法都屬于靜態(tài)的結構重構,也可以在設計階段針對模型進行。如果在設計階段進行此類重構,則需要重新進行正向工程(Forward Engineering),而且原來的代碼會自動注釋掉,需要重新編碼。如果在代碼環(huán)境中進行重構,則會自動實現(xiàn)重構之后的所有代碼。,,(3) 引入常量、變量和方法(Introduce Constant and Variable,Extract Method):將程序中的常數(shù)定義成常量、表達式定義成變量、代碼片斷定義成方法都是代碼結構的改進。也可以把局部變量轉換
46、成屬性變量,即全局變量。(4) 改變方法參數(shù)(Change Method Parameter):方法的參數(shù)是方法簽名的一部分,是方法調(diào)用中動態(tài)變化的地方。修改參數(shù)實際上就是修改方法簽名。在提取方法重構中,可以將方法中表達式代碼中的常數(shù)、變量或者表達式轉換成方法參數(shù),這樣該方法就具有更一般的意義。,,(5) 泛化類型(Generalize Type):使用父類型代替子類型。這樣的程序更具有一般性,更能適應變化。例如:定義一個集合類型變量,使用ArrayList v= new ArrayList(); 重構成List v = new ArrayList(),這樣將來代碼無論改成List v = n
47、ew LinkedList()還是List v = new Vector(),其余代碼都不受影響。(6) 匿名類轉換為內(nèi)部類(Anonymous class to Inner Class):匿名類轉換成內(nèi)部類,內(nèi)部類轉換成外部類,從而提高可重用性。,,(7) 還原方法:是抽取方法(Extract Method)的逆過程。使用“方法調(diào)用”可以改善程序結構,但是這樣勢必要增加調(diào)用開銷。若某些方法只有一個調(diào)用者,就可以把該方法的代碼放入調(diào)用者,以減少調(diào)用開銷,改進性能。(8) 封裝屬性(Encapsulation attribute):是旨在提高程序封裝性的一種重構方法。將屬性定義成私有的,并提供s
48、et/get方法訪問。 (9) 屬性、方法上移或下移(Attribute Move up):將子類中的屬性或者方法上移到父類中,該屬性和方法可為所有子類共享;或者將父類中的屬性和方法下移到子類中,這樣該屬性和方法只能為該子類獨有。,,(10) 提取父類或者接口(Extract Interface):根據(jù)類中的公有方法,創(chuàng)建父類或者接口,并讓該類繼承所提取的父類,或者實現(xiàn)提取的接口。此類重構方法主要適用于當多個客戶使用同一個接口的子集(不同的客戶使用不同的接口,以保持安全性),或兩個類擁有公共父類或公共接口的時候(兩個類都繼承同一父類或實現(xiàn)同一接口)。例如,下面代碼中的MyClass對外提供了三
49、個公共操作接口。class MyClass public void f1() public void f2() public void f3(),,假設客戶A只能訪問f1()方法,客戶B只能訪問f2()方法,客戶C只能訪問f3()方法,則應該設計成:MyClass實現(xiàn)三個接口InterfaceA、InterfaceB、InterfaceC:class MyClass implements InterfaceA,InterfaceB,InterfaceC public void f1() public void f2() public void f3()interface Interface A
50、 public void f1();Interface Interface B Public void f2();,,在客戶A的訪問代碼中,這樣聲明引用變量,可以保證客戶A只能訪問f1()方法。InterfaceA aobj = new My Class();aobj.f1();在客戶B的訪問代碼中,這樣聲明引用變量,可以保證客戶B只能訪問f2()方法。InterfaceB bobj = new MyClass();bobj.f2();,,(11) 創(chuàng)建代理(Proxy):創(chuàng)建多個方法的代理類。具體地說,這種重構要創(chuàng)建一個類(代理類),該類引用被代理的類實例,提供選定的方法接口。通過調(diào)用被代理
51、類的方法即可實現(xiàn)該方法。這種重構適合于將一個類的某些方法公開給某些客戶,或者用以增加新的方法。創(chuàng)建代理可以實現(xiàn)多種設計模式,如包裝(wrapper)、修飾(decorator)、適配器(adapter)等。,,(12) 對象工廠方法(Object Factory Method):這種重構將會自動定義創(chuàng)建對象實例的工廠方法。這種代碼的優(yōu)勢是可以把創(chuàng)建對象實例的過程標準化、工業(yè)化,從而為對象容器和框架提供基礎。例如,Spring框架就可以根據(jù)在配置文件中定義的類自動實例化對象,支持實現(xiàn)在程序代碼之外替換類的功能。除了上述的重構方法外,諸如把順序結構的代碼修改成選擇結構或者重復結構、將離散的數(shù)據(jù)結構
52、轉換為整體的集合變量等也屬于代碼重構的范疇。經(jīng)過合理重構的代碼結構會更加穩(wěn)定,重用程度會更高,也更容易維護和改進。從開發(fā)者的角度來看,無經(jīng)驗的開發(fā)人員需要重構的次數(shù)明顯要比有經(jīng)驗的開發(fā)人員多,所以掌握重構技術也是由初學者進化到專家的必由之路。,,7.5.3 一個程序結構改進(重構)的例子本節(jié)通過計算多個圖形面積之和的例子來說明程序結構的改進過程和面向對象技術應用的關系,也具體地說明重構技術的應用方法。問題:計算幾種圖形的面積之和。例如:圓、矩形、三角形等。初始的程序代碼如下:,,double s1 = 50 * 50 * 3.1416; //半徑為50的圓double s2 = 20 * 30
53、; //長、寬為20、30的矩形double s3 = 0.5 * 10 * 20; //底邊為10,高為20的三角形double sum = s1 + s2 + s3;//求和 如果要把該段代碼重用于其他計算面積之和的程序中,則幾乎沒有任何可重用的地方。,,第一次改進,數(shù)據(jù)結構+控制結構:使用數(shù)組表示多個圖形面積,然后利用循環(huán)計算其面積之和。double s = new double3;s0 = 50 * 50 * 3.1416;s1 = 20 * 30;s2 = 0.5 * 10 * 20;double sum = 0.0;for (int i=0;i 54、m += si;,,在這次改進中,有些代碼可以用于其他計算面積之和甚至更一般的程序中,如計算多個實數(shù)之和的程序中。但這種重用只是通過復制代碼來實現(xiàn)的。第二次改進:提取方法,引入變量、參數(shù)等。例如:計算圓面積、三角形面積、矩形面積,計算面積之和的方法等。根據(jù)簡單的幾何公式,對于計算圓、矩形、三角形面積及計算多個實數(shù)和的方法分別定義如下:,,double circleArea( double r) // 計算半徑為r的圓面積的方法double rectArea(double a, double b) // 計算長、寬分別為a、b的矩形面積的方法double triangleArea(double 55、s, double h) // 計算底邊為s、高為h的三角形面積的方法double tota(Area(double s),,如果給定參數(shù)的具體值,調(diào)用這些方法就可以計算出具體的圓、矩形、三角形的面積并求其面積和。例如:s0 = circleArea(50); // 計算半徑是50的圓面積s1 = triangleArea(10,5); // 計算底是10,高是5的三角形面積s2 = rectAtrea(10,20); // 計算寬是10,高是20的矩形面積sum = totalArea(s);現(xiàn)在程序中定義的方法可以用于計算多個圓、多個矩形、多個三角形的面積,以及任意多個面積的和。,,試想一 56、下,對于計算三角形面積,還可以已知三角形三邊、兩邊夾角、三角形三個頂點等條件,這樣就會增加如下方法:triangleArea(double s1, double s2, double s3)triangleArea(double s1, double s2 , double alfa);triangleArea(double x1,double y1, double x2,double y2, double x3,double y3),,,對于其他圖形也有類似情形,這樣計算面積的方法數(shù)目也會很快地增長。為了更好地分類這種方法,現(xiàn)在可以引入類,以完成第三次改進,將計算三角形面積的三個方法封裝在三 57、角形類中,但此時方法是靜態(tài)的,也就是說僅僅是命名空間的包裝,此時并不包含數(shù)據(jù),如圖形尺寸的封裝。圖形尺寸是通過三角形方法的參數(shù)傳遞進去的,此時的方法也可以看成是一些公共的實用方法。,,class Triangle public static area(double w, double h) public static area(double s1, double s2, double s3) ,,,這次改進的結果和上次改進的結果沒有本質(zhì)上的改變,都是結構化的改進,也就是程序的結構是由方法的定義和調(diào)用組成的。第四次改進:封裝對象。對于上面封裝的三角形類來說,只包含一些實用方法,并沒有共享三角形的 58、數(shù)據(jù)。實際上作為一個三角形對象,其狀態(tài)或者數(shù)據(jù)是唯一的,所有的方法只是返回其狀態(tài)或者對外提供服務的。只有定義了數(shù)據(jù)及對該數(shù)據(jù)的操作的對象整體,才能更好地反映客觀現(xiàn)實,如下面代碼:,,class Triangle double width, height; public double area() ,,此時的類也可以看成是一種自定義數(shù)據(jù)類型,定義了一組數(shù)據(jù)及其操作。該類可以派生無數(shù)的對象實例,就像使用數(shù)據(jù)類型可以定義很多變量一樣,可以用作定義變量或者分配空間的模板。,類的引入正像數(shù)據(jù)類型的引入,可以增強程序的安全性,只有同種類型的變量才可以在一起運算。以totalArea(double s)為 59、例,該方法本意是計算多個圖形面積和,但實際上只要傳遞進來的是實數(shù),都可以計算,甚至負數(shù)。這是因為方法參數(shù)是實型,如果該參數(shù)定義為totalArea(Triangle shapes),則該方法只能接收Triangle類型的值,這樣就避免了因為錯傳了其他類型或者其他意義的參數(shù)而產(chǎn)生錯誤。但是這樣一來,針對每種圖形類型都需要定義一個計算面積和的方法。這是由于類型個性化所帶來的問題,增加了語法的嚴格性和程序安全性,但是降低了效率??梢酝ㄟ^定義每種具體圖形類的父類來提取其共性,提高代碼效率。,,第五次改進:引入父類和繼承機制。public Triangle extends Shape public do 60、uble area()return 0.0;這樣計算多個圖形面積和的方法就可以定義成如下形式:public double totalArea(Shape s) double sum = 0.0;for(int i=0;i 61、形)中。第六次改進:將父類定義成抽象類或者接口。abstract class Shape abstract double area();,,在第五次改進中引入的父類提高了類型的效率,但是也帶來了一個問題,那就是父類的方法實現(xiàn)問題。父類Shape是一般的圖形類,是一個抽象概念,其計算面積的方法肯定是不存在的或者沒辦法實現(xiàn)的,在上面代碼中令其返回0,實際上是假設或者權宜之計,因為在程序中實際上是沒法調(diào)用該方法的,因此其實現(xiàn)方法也沒有什么意義。因此將其定義成抽象類更合適,這樣計算面積的方法就可以定義為抽象的,只給出接口而不給出實現(xiàn)。這時候父類就純粹變成一種類型了,失去了對象的含義。這種方法可以防止 62、誤用父類,因為抽象類不可以創(chuàng)建實例;也可以統(tǒng)一子類接口,子類必須要實現(xiàn)父類的抽象操作,還可以延遲實現(xiàn),即把操作的實現(xiàn)延遲到子類中去,從而建立更抽象、更通用的程序。,,接口的含義和抽象類類似,其所有的操作都是抽象的。接口是用來抽象幾乎沒有相似性的對象的公共操作機制的。在上述例子中,抽象類是可以利用接口來代替的,表示了計算面積這樣的操作接口。interface CanCalculateArea public double area();,,改成接口實現(xiàn)后,可以計算面積的對象就不止上面的圓、矩形、三角形等圖形,還可以包括長方體、圓柱、錐,甚至實物,如汽車、廠房、零件等。上述程序的主要演化過程用圖表示 63、為如圖7.15所示。從圖7.15中的進化過程可以看出,程序從簡單的變量計算結構最終進化到具有繼承關系的復雜類結構,程序功能也從只能計算確定的簡單圖形面積之和,進化到可以計算任意多個任意圖形的面積之和。這實際上是一段抽象的程序代碼,其模式可以應用于很多情況,例如繪制多個圖形、通知所有視圖對象、讓多個對象都執(zhí)行同名操作等。這段程序代碼的功能就在于遍歷對象集合,執(zhí)行每個對象的同名操作,代碼模板如下:for(Object o: objSet) o.operate (),,由于對象的繼承性和多態(tài)性,集合中的對象可以是任意的,只要繼承自同一個父類即可。每種對象的同名操作operate的實現(xiàn)是不一樣的。代碼 64、即體現(xiàn)了對不同對象操作的共性(如計算面積),又通過子類和多態(tài)體現(xiàn)了每種對象的個性(每種圖形的面積公式是不一樣的)。這段代碼簡潔高效,即保證了安全性,又保證了可擴充性和可維護性,也代表了一種模式(pattern)。從程序結構的角度來看,模式就代表了一種可以解決很多類似問題的抽象程序解決方案,這種抽象的解決方案往往給出的只是程序結構的設計方案,關于模式在7.7節(jié)中有較詳細的說明。,,圖7.15 程序結構的演化過程,,7.6 面向對象軟件工程7.6.1 傳統(tǒng)的面向對象軟件工程傳統(tǒng)的面向對象軟件工程是將結構化的軟件工程生命周期、管理方法和面向對象技術結合的一種軟件工程方法。它將面向對象軟件開發(fā)過程分成 65、面向對象系統(tǒng)分析、面向對象系統(tǒng)設計、面向對象系統(tǒng)實現(xiàn)、面向對象系統(tǒng)測試等階段,其核心技術是面向對象建模和面向對象程序設計。,,在面向對象建模中一般要建立三種模型:對象模型、動態(tài)模型和功能模型。對象模型描述系統(tǒng)中的類及其關系,屬于系統(tǒng)的靜態(tài)結構;動態(tài)模型描述在系統(tǒng)功能的實現(xiàn)過程中系統(tǒng)對象之間的交互過程;功能模型類似于系統(tǒng)的高層數(shù)據(jù)流圖,抽象了系統(tǒng)的主要功能。在傳統(tǒng)的面向對象軟件工程的分析和設計階段,都需要建立這三種模型,只不過涉及的對象范圍、抽象的層次、描述的粒度和細度等有所不同。,,在系統(tǒng)分析期間比較關注現(xiàn)實世界的建模。此時,建立起來的對象模型是業(yè)務模型或稱概念模型。它是對現(xiàn)實世界事物及其關系 66、的直接反映,較少涉及系統(tǒng)實現(xiàn)方法和系統(tǒng)對象的描述(分析階段涉及到的系統(tǒng)對象多是抽象的,如界面對象等)。在此階段的對象一般稱為業(yè)務對象或者分析對象。此時建立的動態(tài)模型也是針對在業(yè)務功能的實現(xiàn)過程中,業(yè)務對象之間交互過程的描述。功能模型則從系統(tǒng)外部或比較高的層次上去抽取系統(tǒng)的功能。,,系統(tǒng)設計階段則要考慮系統(tǒng)的實現(xiàn)方案,比如說確定系統(tǒng)運行模式、考慮系統(tǒng)軟件分層架構等,要考慮系統(tǒng)的界面、控制等因素。分析階段建立的各種模型作為設計階段的輸入,在設計階段中對前期工作進行系統(tǒng)化的包裝,使其更適合于信息系統(tǒng)中的實現(xiàn)。例如給業(yè)務對象包裝上界面類,將其放在某個系統(tǒng)架構(如基于組件的架構)下進行物理設計等。即使是原來的概念對象模型(業(yè)務模型),也需要進一步的綜合、優(yōu)化、分離、抽象(如使用分析模式和設計模式等),以適合于系統(tǒng)的目標和信息系統(tǒng)的特點,滿足系統(tǒng)的穩(wěn)定性、維護性、重用性、移植性、分布性等要求。設計階段的動態(tài)模型則是針對在系統(tǒng)功能執(zhí)行過程中所有系統(tǒng)對象的交互過程進行建模。功能模型則應該進一步細化成整個系統(tǒng)的功能而不僅僅是業(yè)務功能。,,可以這樣說,分析的任務是將現(xiàn)實世界中或者問題域中的概念抽象出來,提
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。