相關數據是否封裝/封裝之後是否隱藏

當一個類包含(組合)了許多數據成員,是否需要把其中某一些相關性很大的數據提取出來,重構成一個或幾個小對象,然後讓原來的大類直接組合這些小對象呢?

當滿足以下兩種情況之一時,這種重構是有必要的:

(1)         存在專門針對這些數據的操作;

(2)         還有其它的類或package也包含這些數據。

第一種情況有必要,因爲我們不僅提取了數據,也提取了方法。結果就是提取了一個同時擁有狀態和行爲的對象,而不僅僅是一個數據結構體。這將使原來那個大類的代碼顯得更加清晰,因爲抽象被更好地層次化了。

第二種情況有必要,則僅僅是從代碼複用的角度考慮的,抽取出來,大家都可以用,免得每次填加一個相關的新類時就需要從別人那裏拷貝一大堆數據成員,也避免了當又有新的數據需要加入到這些成員中時,我們要修改一大堆類。

如果這兩個條件都不滿足,那麼這種重構僅僅能使代碼的結構和抽象稍微乾淨一些,並沒有其它重要意義。還是省出時間來乾點別的事吧。或者等代碼進化到出現以上兩種需求時,再重構也不遲。

 

然後,當我們完成這種重構之後,這些新的小類是否有必要公開給其它的類,以及其它的package呢?這就要看這個新的小類僅僅是這個類(或者這個package)的實現細節,還是一種更通用的抽象實體。

如果是後者,無疑應該公開出來。但如果是前者,那就有必要隱藏它,不讓其它類知道。比如在C++語言中,把它定義在某個cpp文件中(而不是頭文件中),或者在C#JAVA這樣的語言中,把它定義成非公共的類。

但是,如果類的對外接口(公共方法公共成員函數)中出現了這種新的類型,該怎麼辦呢?是不是就沒有辦法,只能公開了?比如,類有某些getset方法是專門跟這種小對象打交道的。對於僅僅是實現細節的情況,答案仍然是:隱藏它!寧可讓這些接口中出現重構之前的零散數據,也不要出現這種新的類型。因爲這樣可以減少類或者package之間的耦合。讓外界儘量少地依賴實現細節總是好事。

 

舉個例子:工資單類(Payment)中可能包含一些假期數據,比如vacationType(病假、事假還是其它?),日期date(哪天休的假),小時數hours,我們可能會把這些信息提取出來,封裝成一個新的類:VacationInfo,然後讓Payment直接包含一組VacatonInfo對象。

Payment類有一個公共方法,addVacationInfo。那麼,這個方法的參數該如何設計呢?可以考慮兩種方式:

(1)         void addVacationInfo(const VactionInfo& v);

(2)         void addVacationInfo(VacationType type, Date, date, int hours);

如果Vacation是一種更通用的抽象實體,有必要公開給外界,那就應採用第一種;相反,如果它只是一種實現細節,應該隱藏在類或Package實現的內部,那就應採用第二種。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章