決定把責(zé)任放在哪兒,即使不是最重要的事情, 也是最重要的事之一.
Move Method
和Move Field
簡單地移動對象行為. 如果這兩個重構(gòu)手法都需要用到, 我會首先使用Move Field
, 再使用Move Method
類往往會因為承擔(dān)過多責(zé)任而變得臃腫不堪. 這種情況下, 我會使用Extract Class
將一部分責(zé)任分離出去. 如果一個類變得太不負責(zé)任
, 我就會使用Inline Class
將它融入另一個類. 如果一個類使用了另一類, 運用Hide Delegate
將這種關(guān)系隱藏起來通常是有幫助的. 有時候隱藏委托類會導(dǎo)致?lián)碛姓叩慕涌诮?jīng)常變化, 此時需要使用Remove Middle Man
當(dāng)我不能訪問某個類的源碼, 卻又想把其他責(zé)任移進這個不可修改的類時, 我才會使用這兩個重構(gòu)手法. 如果我想加入的只是一或兩個函數(shù), 就會使用Introduce Foreign Method
: 如果不止一兩個函數(shù), 就使用Introduce Local Extension
7.1 Move Method (搬移函數(shù))
你的程序中, 有個函數(shù)與其所駐類之外的另一個類進行更多的交流: 調(diào)用后者,或被后者調(diào)用.
在該函數(shù)最常用的類中建立一個有這類似行為的新函數(shù). 將舊函數(shù)變成一個單純的委托函數(shù), 或是將就函數(shù)完全移除.
7.2 Move Field (搬移字段)
你的程序中, 某個字段被其所駐類之外的另一個類更多地用到.
在另一個類中新建一個字段, 修改源字段的所有用戶, 令他們改用新字段.
7.3 Extract Class(提煉類)
某個類做了應(yīng)該由兩個類做的事.
建立一個新類, 將相關(guān)的字段和函數(shù)從舊類搬移到新類.
如果你發(fā)現(xiàn)子類化只影響類的部分特性,或如果你發(fā)現(xiàn)某些特性需要以一種方式來子類化, 某些特性則需要以另一種方式子類化, 這就意味著你需要分解原來的類.
7.4 Inline Class(將類內(nèi)聯(lián)化)
某個類沒有做太多事情
將這個類的所有特性搬移到另一個類中, 然后移除原類.
7.5 Hide Delegate(隱藏"委托關(guān)系")
客戶通過一個委托類來調(diào)用另一個對象.
在服務(wù)類上建立客戶端所需的所有函數(shù), 用以隱藏委托關(guān)系
此條體現(xiàn)了對象技術(shù)的關(guān)鍵特征:封裝
如果某個客戶先通過服務(wù)對象的字段得到另一個對象, 然后調(diào)用后者的函數(shù), 那么客戶就必須知曉這一層委托關(guān)系. 你可以在服務(wù)對象上放置一個簡單的委托函數(shù), 將委托關(guān)系隱藏起來, 從而去除這種依賴.
可能隨著提煉類
, 都不用持有委托函數(shù), 直接暴露委托的功能.
它的代價是: 每當(dāng)客戶要使用委托類的新功能, 你就必須在服務(wù)端添加一個簡單委托函數(shù).
7.6 Remove Middle Man(移除中間人)
某個類做了過多的簡單委托動作.
讓客戶直接調(diào)動委托類
此條和7.5
是互斥的關(guān)系, 很難說什么程度的隱藏才是合適的. 隨著系統(tǒng)的變化, 隱藏程度需要不斷的調(diào)整.
- 重構(gòu)的意義就在于:
你永遠不必說對不起 --- 只要把出問題的地方修復(fù)好就行了
7.7 Introduce Foreign Method(引入外加函數(shù))
你需要為提供服務(wù)的類添加一個函數(shù), 但你無法修改這個類.
在客戶類中建立一個函數(shù), 并以第一參數(shù)形式傳入一個服務(wù)類實例
在進行本項重構(gòu)時, 如果你以外加函數(shù)實現(xiàn)一項功能, 那就是一個明確信號: 這個函數(shù)原本應(yīng)該在提供服務(wù)的類中實現(xiàn).
但是不要忘記: 外加函數(shù)終歸是權(quán)宜之計. 如果不能把外加函數(shù)搬移到服務(wù)類中, 就把外加函數(shù)交給服務(wù)類的持有者, 請他幫你在服務(wù)類中實現(xiàn)這個函數(shù).施行7.8操作.
7.8 Introduce Local Extension (引入本地擴展)
你需要為服務(wù)類提供一些額外函數(shù), 但你無需修改這個類
建立一個新類, 使它包含這些額外函數(shù). 讓這個擴展品成為源類的子類或者包裝類.
- 使用本地擴展使你堅持
函數(shù)和數(shù)據(jù)應(yīng)該被統(tǒng)一封裝
的原則. 把零亂的代碼整理放入擴展類中, 使其易于復(fù)用. - 你需要在父類對象創(chuàng)建之前使用本地擴展.