前言
目前在軟件開發領域有兩種主流的開發方法:結構化開發和面向對象開發。結構化開發是一種比較傳統的開發方法,早期的高級編程語言,如Basic、C. Fortran和Pascal等,都是支持結構化開發的編程語言。隨著軟件開發技術的逐步發展,為了進一步提高軟件的可重用性、可擴展性和可維護性,面向對象的編程語言及面向對象設計理論應運而生,JAVA語言就是一種純面向對象的編程語言。
一般說來,軟件開發都會經歷以下生命周期:
- 軟件分析:分析問題領域,了解用戶的需求。
- 軟件設計: 確定軟件的總體架構,把整個軟件系統劃分成大大小小的多個子系統,設計每個子系統的具體結構。
- 軟件編碼:用選定的編程語言來編寫程序代碼,實現在設計階段勾畫出的軟件藍圖。
- 軟件測試:測試軟件是否能實現特定的功能,以及測試軟件的運行性能。
- 軟件部署:為用戶安裝軟件系統,幫助用戶正確地使用軟件。
- 軟件維護:修復軟件中存在的Bug,當用戶需求發生變化時( 增加新的功能,或者修改已有功能的實現方式),修改相應的軟件。
為了提高軟件開發效率,降低軟件開發成本,一個優良的軟件系統應該具備以下特點:
- 可重用性:減少軟件中的重復代碼,避免重復編程。
- 可擴展性:當軟件必須增加新的功能時,能夠在現有系統結構的基礎上,方便地創建新的子系統,不需要改變軟件系統現有的結構,也不會影響已經存在的子系統。
- 可維護性:當用戶需求發生變化時,只需要修改局部的子系統的少量程序代碼,不會牽一發而動全身, 修改軟件系統中多個子系統的程序代碼。
架構化的軟件開發方法簡介
結構化開發方法主要是按照功能來劃分軟件結構的,它把軟件系統的功能看作是根據給定的輸入數據,進行相應的運算,然后輸出結果,如下圖所示。
進行結構化設計時,首先考慮整個軟件系統的功能,然后按照模塊劃分的一些基本原則(比如內聚性和松耦合)等,對功能進行分解,把整個軟件系統劃分成多個模塊,每個模塊實現特定的子功能。為了提高軟件的內聚性,在模塊中還會把功能分解到更小的子模塊中。在完成所有的模塊設計后,把這些模塊拼裝起來,就構成了整個軟件系統。軟件系統可看作是多個子系統的集合,每個子系統都是具有輸入/輸出功能的模塊,如下圖所示。
結構化設計屬于自頂向下的設計,在設計階段就不得不考慮如何實現系統的功能,因為分解功能的過程其實就是實現功能的過程。結構化設計的局限性在于不能靈活地適應用戶不斷變化的需求。當用戶需求發生變化,比如要求修改現有軟件功能的實現方式或者要求追加新的功能時,就需要自頂向下地修改模塊的結構,有時候甚至整個軟件系統的設計被完全推翻。
在進行結構化編程時,程序的主體是方法,方法是最小的功能模塊,每個方法都是具有輸入/輸出功能的子系統,方法的輸入數據來自于方法參數、全局變量和常量,方法的輸出數據包括方法返回值,以及指針類型的方法參數。一組相關的方法組合成大的功能模塊。
面向對象的軟件開發方法簡介
面向對象的開發方法把軟件系統看成是各種對象的集合,對象就是最小的子系統,一組相關的對象能夠組合成更復雜的子系統。面向對象的開發方法具有以下優點:
- 把軟件系統看成是各種對象的集合,這更接近人類認識世界的自然思維方式。
- 軟件需求的變動往往是功能的變動,而功能的執行者一對象一般不會有大的變化。這使得按照對象設計出來的系統結構比較穩定。
- 對象包括屬性 (數據)和行為(方法),對象把數據及方法的具體實現方式一起封裝起來,這使得方法和與之相關的數據不再分離,提高了每個子系統的相對獨立性,從而提高了軟件的可維護性。
- 支持封裝、抽象、繼承和多態等各種特征,提高了軟件的可重用性、可維護性和可擴展性。這些特征將在后面的章節中詳述。
廣義地講,面向對象編程是結構化編程的一種改進實現方式。傳統的面向過程的結構化編程的最小子系統是功能模塊,而面向對象編程的最小子系統是對象。
對象模型
在面向對象的分析和設計階段,致力于建立模擬問題領域的對象模型。建立對象模型既包括自底向上的抽象過程,也包括自頂向下的分解過程。
(1)自底向上的抽象。
建立對象模型的第一步是從問題領域的陳述入手。分析需求的過程與對象模型的形成過程一致,開發人員與用戶的交談是從用戶熟悉的問題領域中的事物(具體實例)開始的,這就使用戶與開發人員之間有了共同語言,使得開發人員能徹底搞清用戶需求,然后再建立正確的對象模型。開發人員需要進行以下自底向上的抽象思維:
- 把問題領域中的事物抽象為具有特定屬性和行為的對象。比如一個模擬動物園的程序中,存在各種小動物對象,比如各種小貓、小狗等。
- 把具有相同屬性和行為的對象抽象為類。比如盡管各種小貓、小狗等對象各自不同,但是它們具有相同的屬性和行為,所以可以將各種小貓對象抽象為小貓類,而各種小狗對象抽象為小狗類。
- 當多個類之間存在一些共性(具有相同屬性和行為)時,把這些共性抽象到父類中。比如在前面的例子中,小貓類和小狗類又可以進一步歸于哺乳動物類。
(2)自頂向下的分解。
在建立對象模型的過程中,也包括自頂向下的分解。例如對于計算機系統,首先識別出主機對象、顯示器對象、鍵盤對象和打印機對象等。接著對這些對象再進一步分解,例如主機對象由處理器對象、內存對象、硬盤對象和主板對象等組成。系統的進一步分解因有具體的對象為依據,所以分解過程比較明確,而且也相對容易。所以面向對象建模也具有自頂向下開發方法的優點,既能有效地控制系統的復雜性,又同時避免了結構化開發方法中功能分解的困難和不確定性。
UML:可視化建模語言
面向對象的分析與設計方法,在20世紀80年代末至90年代中發展到一個高潮。但是,諸多流派在思想和術語上有很多不同的提法,對術語和概念的運用也各不相同,統一是繼續發展的必然趨勢。需要用一種統一的符號來描述在軟件分析和設計階段勾畫出來的對象模型,統一.建模語言(Unified Modeling Language, UML)應運而生。
UML是一種定義良好、易于表達、功能強大且普遍適用的可視化建模語言。它吸取了諸多流派的優點,而且有進一步的發展,最終成為大眾所共同接受的標準建模語言。
面向對象開發中的核心思想和概念
在面向對象的軟件開發過程中,開發者的主要任務就是先建立模擬問題領域的對象模型,然后通過程序代碼來實現對象模型。到底如何建立對象模型,如何用程序代碼實現對象模型,并且能保證軟件系統的可重用、可擴展和可維護性呢?
問題領域、對象、屬性、狀態、行為、方法、實現
問題領域是指軟件系統所模擬的真實世界中的系統。隨著計算機技術的發展和普及,軟件系統滲透到社會的各個方面,幾乎可用來模擬任意一種問題領域,如學校、醫院、商場、銀行、電影攝制組和太陽系等。
對象是對問題領域中事物的抽象。對象具有以下特性:
(1)萬物皆為對象。問題領域中的實體和概念都可以抽象為對象。例如在學校領域,對象包括學生、成績單、教師、課程和教室等:在銀行領域,對象包括銀行賬戶、出納員、支票、匯率、現金和驗鈔機等;在商場領域,對象包括客戶、商品、訂單、發票、倉庫和營業員等:在電影攝制組領域,對象包括演員、導演、電影、道具和化妝師等;在太陽系領域,對象包括太陽、月亮、地球、火星和木星等;在用Java語言創建的圖形用戶界面中,窗口、滾動面板、按鈕、列表、菜單和文本框等也都是對象。
(2)每個對象都是唯一-的。對象的唯一性來自于真實世界中事物的唯一性。世界上不存在兩片一模一樣的葉子,因此在軟件系統中用來模擬每片葉子的對象也具有唯一性。例如學校領域的學生小張、學生小王、小張的成績單和小王的成績單,這些都是唯一的對象。在Java虛擬機提供的運行時環境中,保證每個對象的唯一性的手段是為它在內存中分配唯一的地址。
(3)對象具有屬性和行為。例如小張,性別女,年齡15,身高1.6米,體重40kg, 能夠學習、唱歌和打羽毛球。小張的屬性包括:姓名、性別、年齡、身高和體重。小張的行為包括:學習、唱歌和打羽毛球。例如一部手機:品牌名稱是諾基亞,價格是2000元,銀白色,能夠拍照、打電話和收發短信等。這只手機的屬性包括:品牌類型type、 價格price 和顏色color,行為包括拍照takePhoto()、 打電話call)、 收短信sendMessage(和發短信receiveMessage()。
同一個類的所有實例具有相同屬性,表明它們的屬性的含義相同,但是它們的狀態不一定相同,也就是屬性取值不一定相同。例如演員小紅、小白和小黃,都有姓名、性別、年齡、身高和體重這些屬性,但是他們的屬性取值不同。
同一個類的所有實例包括類本身的所有實例,以及其子類的所有實例。類的所有實例具有相同行為,意味著它們具有一些相同的功能。類本身的所有實例按同樣的方式實現相同的功能,而子類與父類之間,以及子類之間的實例則可能采用不同的方式來實現相同的功能。
類、類型
類是一組具有相同屬性和行為的對象的抽象。類及類的關系構成了對象模型的主要內容。如下圖所示,對象模型用來模擬問題領域,Java 程序實現對象模型,Java程序運行在Java虛擬機提供的運行時環境中,Java虛擬機運行在計算機機器上。
計算機受其存儲單元的限制,只能表示和操作一些基本的數據類型,比如整數、字符和浮點數。對象模型中的類可以看作是開發人員自定義的數據類型,Java 虛擬機的運行時環境封裝了把自定義的數據類型映射到計算機的內置數據類型的過程,使得開發人員不必受到計算機的內置數據類型的限制,對任意一種問題領域,都可以方便地根據識別對象、再進行分類(創建任意的數據類型)的思路來建立對象模型。
消息、服務
軟件系統的復雜功能是由各種對象向電視機對象發送一個“開機”消息。電視機對象接受到這個“開機”消息,執行相應的開機操作。此外,遙控器還能向電視機發送其他消息,例如選擇頻道、調節音量、播放VCD和關機等。
每個對象都具有特定的功能,相對于其他對象而言,它的功能就是為其他對象提供的服務。例如電視機具有的功能包括:開機、關機、選擇頻道、調節音量和播放VCD等。遙控器為了獲得電視機的服務,需要向電視機提出獲得特定服務的請求,提出請求的過程稱為發送消息。對象提供的服務是由對象的方法來實現的,因此發送消息實際上也就是調用一個對象的方法。
接口
既然每個對象是服務提供者,那么如何對外提供服務呢?對象通過接口對外提供服務。例如電視機的紅外線接收器就是為遙控器提供的接口。再比如在日常生活中經常接觸的電源插口,如果把整個供電系統看作-一個對象,那么它提供的主要服務就是供電。如何提供這一服務呢? 很簡單,只要在住宅里布置好線路,提供一些電源插口,各種電器就能從電源插口中獲得電源了。電源插口就是供電系統為各種電器提供的接口。此外,鼠標上的按鈕、鍵盤上的按鈕、洗衣機上的按鈕、電燈的開關都是為用戶提供的接口。
在現實世界中,接口也是實體,比如電源插口、洗衣機上的按鈕和電燈的開關。而在面向對象的范疇中,接口是一個抽象的概念,是指系統對外提供的所有服務。系統的接口描述系統能夠提供哪些服務,但是不包含服務的實現細節。這里的系統既可以指整個軟件系統,也可以指一個子系統。對象是最小的子系統,每個對象都是服務提供者,因此每個對象都有接口。
在Java語言中,接口有兩種意思:
- 一是指以上介紹的概念性的接口,即指系統對外提供的所有服務,在對象中表現為public類型的方法的聲明。
- 二是指用interface 關鍵字定義的實實在在的接口,也稱為接口類型,它用于明確地描述系統對外提供的所有服務,它能夠更加清晰地把系統的實現細節與接口分離。
封裝
封裝是指隱藏對象的屬性和實現細節,僅僅對外公開接口。封裝能為軟件系統帶來以下優點:
(1)便于使用者正確、方便地理解和使用系統,防止使用者錯誤修改系統的屬性。還是以供電系統為例,過去房屋墻壁的.上方都是電線,現在的房屋里電線都“不見”了,在墻壁上只露出了一些電源插口。為什么要把電線藏起來呢?理由很簡單,暴露在外面的電線不安全、也不美觀。
再比如電視機系統,盡管它本身的實現很復雜,但用戶使用起來卻非常簡單,只要通過遙控器上的幾個按鈕就能享受電視機提供的服務。電視機的實現細節被藏在它的大殼子里,沒有必要向用戶公開。
(2)有助于建立各個系統之間的松耦合關系,提高系統的獨立性。當某一個系統的實現發生變化,只要它的接口不變,就不會影響到其他的系統。
(3)提高軟件的可重用性,每個系統都是-一個相對獨立的整體,可以在多種環境中得到重用。例如干電池就是- -個可重用的獨立系統,在相機、手電筒、電動剃須刀和玩具賽車中都能發揮作用。
(4)降低了構建大型系統的風險,即使整個系統不成功,個別的獨立子系統有可能依然是有價值的。例如相機損壞了,它的干電池依然有用,可以安裝到手電筒中。
一個設計良好的系統會封裝所有的實現細節,把它的接口與實現清晰地隔離開來,系統之間只通過接口進行通信。面向對象的編程語言主要是通過訪問控制機制來進行封裝的,這種機制能控制對象的屬性和方法的可訪問性。在Java語言中提供了4種訪問控制級別:
- public:對外公開,訪問級別最高。
- protected:只對同一個包中的類或者子類公開。
- 默認:只對同一個包中的類公開。
- private:不對外公開,只能在對象內部訪問,訪問級別最低。
繼承
在父類和子類之間同時存在著繼承和擴展關系。子類繼承了父類的屬性和方法,同時,子類中還可以擴展出新的屬性和方法,并且還可以覆蓋父類中方法的實現方式。覆蓋也是專用術語,是指在子類中重新實現父類中的方法。
從每個對象都是服務提供者的角度來理解,子類會提供和父類相同的服務,此外子類還可以提供父類所沒有的服務,或者覆蓋父類中服務的實現方式。例如手機,早期生產的手機具有打電話的功能,但不具有拍照功能,現在的一些新款手機繼承了打電話的功能,而且增加了拍照功能。
繼承與擴展同時提高了系統的可重用性和可擴展性。例如,手機和計算機之所以能迅猛地更新換代,具備越來越多的功能,就是因為當廠商在生產新型號的手機和計算機時,他們不必從頭生產,而是在原有手機和計算機的基礎上進行升級。
繼承與擴展導致面向對象的軟件開發領域中架構類軟件系統的發展。從頭構建一個復雜軟件系統的工作量巨大,為了提高開發效率,有一些組織開發了一些通用的軟件架構。有了這些軟件架構,新的軟件系統就不必從頭開發,只需要在這些通用軟件架構的基礎上進行擴展。
目前在Java領域比較流行的架構軟件包括:
- ?JavaEE:Oracle公司制定的分布式分層的企業應用的軟件架構,它把企業應用分為客戶層、JavaWeb層、應用服務層和數據庫層。在JavaWeb層的擴展點主要是Servlet類和JSP,應用服務層的擴展點主要是EJB組件。
- Struts: Apache開放源代碼組織為JavaWeb應用創建的通用框架,采用模型一視圖一控制器(Model-View-Controller, MVC)設計模式,它的最主要的擴展點是控制器層的Action類。
- JSF:Oracle公司為JavaWeb應用的界面創建的通用框架。
- Spring: Spring 開放源代碼組織為企業應用的服務層創建的通用框架。
UML語言簡介
1997年,對象管理組織(Object Management Group, OMG)發布了統一建模語言(Unified Modeling Language, UML)。UML的目標之一就是為開發團隊提供標準、通用的面向對象設計語言。UML提供了一套IT專業人員期待多年的統一的標準 建模符號。通過使用UML,這些人員能夠閱讀和交流系統架構圖和設計規劃圖,就像建筑人多年來使用建筑設計圖一樣。
UML采用一些標準圖形元素來直觀地表示對象模型,所以它是一種可視化的面向對象的建模語言。UML主要包含以下一些框圖:
- 用例圖(Use Case Diagram):從用戶角度描述系統功能。
- 類框圖(Class Diagram):描述對象模型中類及類之間的關系。
- 狀態轉換圖( State Transition Diagram):描述對象所有可能的狀態,以及導致狀態轉換的轉移條件。只需要為個別具有復雜的狀態轉換過程的類提供狀態轉換圖。
- 時序圖(Sequence Diagram)和協作圖(Cooperation Diagram): 描述對象之間的交互關系。其中時序圖顯示對象之間的動態協作關系,它強調對象之間消息發送的時間順序,同時顯示對象之間的交互;協作圖能直觀地顯示對象之間的協作關系。這兩種圖合稱為交互圖。
- 組件圖(Component Diagram): 描述系統中各個軟件組件之間的依賴關系,還可以描述軟件組件的源代碼的組織結構。
- 部署圖(Deployment Diagram):定義系統中軟硬件的物理體系結構。它可以顯示實際的計算機和設備(用節點表示),以及它們之間的連接關系,在節點中,還可以顯示軟件組件在硬件環境中的布局。
在以上框圖中,其中用例圖、類框圖、組件圖和部署圖等4個圖形,構成了系統的靜態模型;而狀態轉換圖、時序圖和協作圖則構成了系統的動態模型。因此,UML的主要框圖也可以歸納為靜態模型和動態模型兩大類。
總結
本篇結合實際例子,探討了如何運用面向對象思維來構建可維護、可重用和可擴展的軟件系統。面向對象的核心思想和概念包括:抽象、封裝、接口、多態和繼承,靈活運用這些理論武器,就會使得軟件系統像用積木搭起來的系統一 樣,可以方便地進行組裝、拆卸和重用。
喜歡文章請多多點贊評論轉發,關注筆者,后續會再帶來更豐富的學習內容更新,你們的支持就是筆者最大的動力!!!