你好,C++(38)從問題描述中發現對象的屬性和行爲 6.4 工資程序成長記:類與對象(上)

6.4  工資程序成長記:類與對象

「夜半三更喲,盼天明;寒冬臘月喲,盼春風。若要盼得喲,漲工資,嶺上……」自從上次老闆許諾給小陳漲工資之後,一轉眼又過去幾個月了,但是漲工資的事一點動靜都沒有。小陳只好每天哼着這首歌,本身安慰本身,天總會亮的,春天總會來的,而工資也總會漲的。這天,小陳正在哼這首歌,沒想到老闆又讓他去辦公室。小陳心中那個高興啊,心想,盼星星盼月亮,總算盼到了這一天啊。程序員

因而,小陳趕忙來到老闆的辦公室。但是,當他一進辦公室,看到老闆那陰雲密佈的臉就知道狀況不妙。果真,老闆一見小陳就抱怨起來:數組

「小陳啊,你這個工資程序怎麼搞得嘛?你是知道的,咱們公司的工資是按照員工的入職年數來計算的,而且高級員工和通常員工的計算方法不一樣。但是過了一年了,每一個人的工資仍是第一次輸入的數據,沒有變化嘛!還有還有,你這個程序只能找到最高工資的人的序號,只知道序號有什麼用啊,我要知道名字,名字,這樣我纔好直接把他給開了啊……」函數

一聽老闆這一通抱怨,小陳心涼了半截,心想此次漲工資確定又沒戲了。因而有氣無力地說:3d

「老闆,你彆着急,程序就是這樣不斷改進不斷完善的。讓我回去按照你的要求修改修改,保證讓你滿意。」指針

就這樣,在老闆那裏捱了一頓訓以後,小陳又帶着老闆的新要求回來了。小陳簡單地分析了一下老闆的新要求:要讓每一個員工的工資動態計算,而員工又分爲高級員工和通常員工兩種,每種員工的工資計算方法各不相同。在統計的時候,不只須要給出最高工資者的序號,還要給出姓名的信息。這些新的要求看起來還挺複雜的,小陳正撓頭細想解決之道,忽然靈光一閃:這個問題,正好能夠用C++中的面向對象思想來解決啊——利用封裝機制,能夠把員工的序號、入職年份、姓名、工資等信息封裝成員工類,這樣在統計獲得最高工資的員工序號的同時也就獲得了對應的姓名;利用繼承機制,能夠從員工類派生出高級員工類和通常員工類,再配合多態機制,就能夠實現對兩類員工的工資採起不一樣的計算方式了。想到這裏,小陳不禁得一拍小腿,心中感嘆,面向對象思想在解決複雜問題時果真威力無比啊!巧的是,小陳這段時間恰好學過了C++中用類來體現面向對象思想,因而他決定用類來對這個工資程序進行改寫。對象

6.4.1 需求分析:老闆要的是這樣一個工資程序

所謂需求分析,就是搞清楚客戶到底要的是一個什麼樣的軟件。不管這個軟件是用於飛天登月的大型系統,仍是僅供孩子們玩的遊戲程序,需求分析永遠都是咱們開發工做的第一步。因此,當小陳接到老闆下達的任務後,他作的第一件事不是當即修改程序代碼,而是先進行需求的分析,搞清楚老闆到底要的是怎樣一個工資程序。blog

根據老闆的抱怨(在實際的開發實踐中,這每每來自前期的用戶調查),這個工資程序必須可以輸入員工的工資數據,而輸入數據又包括直接從數據文件讀取和手工輸入;完成數據輸入之後,這個程序還要對工資數據進行處理,包括統計最高的工資,以及根據員工的姓名對工資進行查詢;最後,就是將全部的工資數據輸出到文件,以便於下次直接讀取。繼承

通過這樣的簡單需求分析,小陳對老闆想要的工資程序就比較清楚了。爲了讓這些需求更加清晰而直觀,小陳將其繪製成了UML用例圖,老闆要的工資程序,不過就是實現了這些用例的工資程序。接口

最佳實踐:全世界程序員都在說UML遊戲

UML(統一建模語言,Unified Modeling Language),一種描述軟件的經常使用方式,它經過爲軟件創建模型,並經過一系列圖(用例圖、類圖、活動圖等)來直觀地描述軟件的結構和行爲,從而讓程序員對軟件有一個清晰的認識和理解。所以,在具體實現一個軟件以前,咱們都使用它來描述咱們即將開發的軟件,以期在項目團隊中達成對軟件的共識。也正由於如此,整個項目團隊中的成員,甚至是全世界的程序員,都必須掌握這門建模語言。

 

圖6-13 工資程序的用例圖

 

6.4.2  從問題描述中發現對象

完成程序的需求分析後,小陳明白了本身要作的是怎樣的一個軟件,接下來的問題就是怎麼作了。按照面向對象思想解決問題的通常順序,首先就是從問題描述中發現對象。而小陳知道,問題描述中的那些名詞實際上就是對象。

按照「尋找對象就是尋找名詞」的思路,小陳開始尋找這個問題描述中的名詞。首先,遇到的第一個名詞是工資系統(SalarySys)。而後就是該系統所管理的員工(Employee),由於級別的不一樣,員工又分爲高級員工(Officer)和普通員工(Staff),這些就是整個問題中的名詞,也就構成了整個問題所涉及的對象。

從問題描述中除了能夠找到對象以外,還能夠發現對象之間的各類關係:工資系統管理員工對象,它們之間是一對多的關係;同時,高級員工和普通員工同屬於員工,這就表示它們應該有着共同的基類,都是從員工類所派生出來的。圖6-14描述了整個問題中的對象及對象之間的關係。

 

 

圖6-14  工資程序中的對象及對象之間的關係

6.4.3  分析對象的屬性和行爲

在找到對象以後,就能夠進一步分析這些對象所擁有的屬性和行爲,而後利用面向對象的封裝機制將其封裝成具體的類。首先,分析這個問題中最基礎的員工類Employee。根據老闆的要求,爲了找到工資最高的員工,咱們必須記錄每一個員工的姓名(m_strName);爲了根據在職時間(如今時間減去入職時間)動態地計算員工的工資,咱們必須記錄員工的入職時間(m_nYear);員工有級別的差異,各個級別的員工工資計算方式不一樣,應該有一個屬性級別(m_nLevel)來記錄。因此這個對象必需的屬性就是姓名、入職時間和級別。

分析了員工類Employee的屬性,那麼它又該擁有什麼樣的行爲呢?類的行爲都是用來完成需求分析中的用例的,因此,Employee類的行爲跟它要完成的用例密切相關。爲了完成「計算最大值」用例,它應該有一個計算工資的行爲(GetSalary()),能夠根據員工的在職時間動態地計算員工的工資。可是,Employee類做爲具體的員工類Officer和Staff的基類,並不知道工資的具體計算方法,因此這個行爲只是一個接口而已,須要留待它的派生類來具體實現,因此在Employee中這個函數應該是一個純虛函數;而要計算工資,它又必須知道員工的在職時間,因此它還必須有一個得到在職時間的行爲(GetWorkTime());同時,爲了完成「查詢工資」這個用例,程序須要知道員工的姓名,因此員工類應該提供一個得到名字的行爲(GetName());最後,爲了完成「輸出數據到文件」的用例,Employee類還必須提供得到員工級別(GetLevel())和入職年份(GetYear())的行爲,從而能夠獲取員工的信息並將其輸出。

通過這樣的分析,小陳得出了員工類Employee應該具有的屬性和行爲。爲了記錄本身的分析結果,讓結果一目瞭然,小陳將分析結果畫成了UML類圖:

 

圖6-15 Employee類的屬性和行爲

具體的員工類Officer和Staff是Employee的派生類,在Employee類的基礎上,這兩個具體的員工類並無額外的須要描述的內容,因此它們不須要新添加屬性,只須要從基類繼承已有的屬性便可。而至於行爲,具體的員工類須要負責具體的工資計算和返回不一樣的員工級別,因此它們須要實現基類中的GetSalary()和GetLevel()這兩個虛函數。通過這樣的分析,Officer和Staff類應該具有的屬性和方法就很清楚了。小陳將它們用以下的UML類圖來表示:

 

圖6-16 Officer和Staff類的屬性和行爲。

按照一樣的方法,小陳接着分析用於管理這些員工對象的SalarySys類。爲了保存和管理多個Employee對象,SalarySys類必須有一個數組來保存這些對象,而爲了應用面向對象的多態機制來動態地計算員工工資,數組中保存的不該該是這些對象自己,而應該是指向這些對象的指針;同時,數組只是表示了SalarySys所可以保存的最多的對象指針,可是並非數組中的每一個指針都是有效的,具體保存了多少個指針還不清楚,咱們還必須用一個屬性來表示當前有效的指針的個數(m_nCount);另外,SalarySys須要從文件讀取數據,最後還須要將數據寫入文件,因此它還須要一個記錄數據文件名的屬性(m_strFileName)。

在SalarySys類的行爲上,小陳仍是一樣從它要完成的用例來分析。根據他以前對這個程序進行的簡單需求分析,SalarySys首先須要完成「輸入數據」這個用例,而這個用例又包含了「從文件讀取」和「手工輸入」這兩個用例,這就要求SalarySys類應該具備從文件讀取數據(Read())和讓用戶手工輸入(Input())的行爲;完成「輸入數據」以後,就是「處理數據」,它也一樣包括了「計算最大值」和「查詢工資」兩個用例,這就要求SalarySys類具備查找全部工資數據中的最大值(GetMax())和根據用戶輸入的姓名查詢相應工資信息(Find())的行爲;最後,就是「輸出數據」這個用例,它要求SalarySys具備將全部工資數據保存到數據文件(Write())的行爲。

分析完成以後,小陳一樣將分析結果繪製成了UML類圖:

 

圖6-17 SalarySys類的屬性和行爲

相關文章
相關標籤/搜索