一.自封裝字段
你直接訪問乙個字段,但與字段之間的耦合關係逐漸變得笨拙。為這個字段建立取值/設值函式,並且只以這些函式來訪問字段。
在字段訪問方式這個問題上,存在兩種截然不同的觀點。其中一派認為,在該變數定義所在的類中,你可以自由訪問它;另一派認為,即使在這個類中你也應該只使用訪問函式間接訪問。兩派之間的爭論客戶已說是如火如荼。歸根結底,間接訪問變數的好處是,子類可以通過覆寫乙個函式而改變獲取資料的途徑,它還支援更靈活的資料管理方式,例如延遲初始化(意思是:只有在需要用到某值時,才對它初始化)。直接訪問變數的好處則是:**比較容易閱讀。面臨選擇時,就我自己而言,我比較喜歡先使用直接訪問方式,知道這種方式帶來麻煩為止。
二.以物件取代資料值
你有乙個資料項,需要與其他資料和行為一起使用才用意義。開發初期,你往往決定以簡單的資料項表示簡單的情況。但是,隨著開發的進行,你可能會發現,這些簡單資料項不再那麼簡單了。比如說,一開始你可能會用乙個字串來表示**號碼的概念,但是隨後你會發現,**號碼需要格式化,抽取區號之類的特殊行為。如果這樣的資料項只有一兩個,你還可以把相關函式放進資料項所屬的物件裡。但是重複**壞味道和依戀清潔壞味道很快就會從**中散發出來。當這些壞味道開始出現,你就應該將資料值變成物件。
三.將值物件改為引用物件
你從乙個類衍生出許多彼此相等的例項,希望將它們替換為同乙個物件。在許多系統中,你都可以對物件做乙個有用的分類,引用物件和值物件。前者就像客戶,賬戶這樣的東西,每個物件代表真實世界中的乙個實物,你可以直接以相等操作符(==)檢查兩個物件是否相等。後者則是像日期,錢這樣的東西,它們完全由其所含的資料值來定義,你並不在意副本的存在,系統中或許存在成百上千個內容為"1/1/2000"的日期物件,當然你需要知道兩個值物件是否相等,需要覆寫equals()方法。要在引用物件和值物件之間做選擇有時並不容易。有時候你會從乙個簡單的值物件開始,在其中儲存少量不可修改的資料。而後,你可能會希望給這個物件加入一些可修改資料,並確保對任何乙個物件的修改都能影響到所有引用此物件的地方。這時候你就需要將這個物件程式設計乙個引用物件。
四.以物件取代陣列
你有乙個陣列,其中的元素各自代表不同的東西。陣列是一種常見的用以組織資料的結構,不過他們應該只用於"以某種順序容納一組相似物件"。有時候你會發現,乙個陣列容納了多種不同物件,這會給使用者帶來麻煩,因為他們很難記住像陣列的第乙個元素時人名這樣的約定。物件就不同了,你可以運用欄位名稱和函式名稱來傳達這樣的資訊,因此你無須死記它,也無需依賴注釋。
五.複製被監視資料
你有一些領域資料置身於gui控制項中,而領域函式需要訪問這些資料,將該資料複製到乙個領域物件中,建立乙個observer模式,用以同步領域物件和gui物件內的重複資料。
乙個分層良好的系統,應該將處理使用者介面和處理業務邏輯的**分開。之所以這樣做,原因有以下幾點:
1.你可能需要使用不同的使用者介面來表現相同的業務邏輯,如果同時承擔兩種責任,使用者介面會變得過分複雜。
2.與gui隔離之後,領域物件的維護和演化都會更容易,你甚至可以讓不同的開發者負責不同部分的開發。
儘管可以輕鬆地將行為劃分到不同部位,資料卻往往不能如此。同一項資料有可能既需要內嵌於gui控制項,也需要儲存於領域模型裡。自從mvc模式出現後,使用者介面框架都使用多層系統來提供某種機制,使你不但可以提供這類資料,並保持它們同步。如果你遇到的**是以兩層方式開發,業務邏輯被內嵌於使用者介面之中,你就有必要將行為分離出來。其中的主要工作就是函式的分解和搬移。但資料就不同了,你不能僅僅只是移動資料,必須將它複製到新的物件中,並提供相應的同步機制。
六.以欄位取代子類
你的各個子類的唯一差別只在返回常量資料的函式身上。修改這些函式,使它們返回超類中的某個(新增)字段 ,然後銷毀子類。
建立子類的目的,是為了增加新特性或變化其行為。有一種變化行為被稱為"常量函式",它們會返回乙個硬編碼的值。這東西有其用途:你可以讓不同的子類中的同乙個訪問函式返回不同的值。你可以在超類中將訪問函式宣告為抽象函式,並在不同的子類中讓它返回不同的值。
儘管常量函式有其用途,但若子類中只有常量函式,實在沒有足夠的存在價值。你可以在超類中設計乙個與常量函式返回值對應的字段,從而完全去除這樣的子類。如此一來就可以避免因繼承而帶來的額外複雜性。
重構 重新組織資料
1 self encapsulate field 自封裝字段 為這個字段建立取值 設定函式,且只通過這個函式訪問該欄位。2 replace data value with object 以物件取代資料值 有乙個資料項,需要與其他資料和行為一起使用才有意義。將資料項變成物件。3 change valu...
重構之重新組織函式 Inline Temp
inline temp 概述 乙個臨時變數,只被乙個簡單表示式賦值一次,而它妨礙了其它重構手法。動機 motivation inline temp多半是作為replace temp with query的一部分來使用。惟一單獨使用inline temp的情況是 你發現某個臨時變數被賦予某個函式呼叫的...
重構手法之重新組織函式 5
返回總目錄 本小節目錄 你有乙個大型函式,其中對區域性變數的使用使你無法採用extract method。將這個函式放進乙個單獨物件中,如此一來區域性變數就成了物件內的字段。然後你可以在同乙個物件中將這個大型函式分解為多個小型函式。我們一直在強調,小型函式優美動人。只要將相對獨立的 從大型函式中提煉...