1、字段上移
修改點:兩個子類擁有相同的字段
做法:將該字段移至父類
2、函數上移
修改點:有些函數,在各個子類中產生完全相同的效果
做法:將該函數移至父類
有一種特殊情況也需要這麼做:子類函數覆蓋了父類的,但是仍然做著相同的工作
在此重構中你可能會遇到一種情況,就是你提煉的函數調用了子類有而父類沒有的函數,那麼在父類中給此父類沒有的函數,建立一個虛函數即可。
3、構造函數本體上移
修改點:你在各個子類中擁有一些構造函數,它們的本體幾乎完全一致
做法:在父類中新建一個構造函數,並在子類構造函數中調用它。
4、函數下移
修改點:父類中的某個函數只與部分(而非全部)子類有關
做法:將這個函數移到相關的那些子類去。
5、字段下移
修改點:父類中某個字段只被部分(而非全部)子類用到
做法:講這個字段下移到相關的子類去。
6、提煉子類
修改點:類中的某些特性只被某些(而非全部)實例用到
做法:新建一個類,將上面所說的那一部分特性移至子類
7、提煉父類
修改點:兩個類有相似特性
做法:為這兩個類建立一個父類,將相同特性移至超類
8、提煉接口
修改點:若干客戶使用類接口中的同一子集,或者兩個類的接口有部分相同
做法:將相同子集提煉到一個獨立接口
意思很簡單,就是將一個類裡的一些業務相關的函數,或者是兩個類中部分相同的函數,提取為Interface(這裡不用接口用個英文的原因是在前面的文章中接口一詞可能更多的可以理解為一個類的公共函數)
9、折疊繼承體系
修改點:父類和子類無太大區別
做法:將它們合為一體
10、塑造模版函數
修改點:你有一些子類,其中相應的某些函數以相同順序執行類似的操作,但各個操作的細節上有所不同
做法:將這些操作分別放進獨立函數中,並保持它們具有相同的簽名,於是原函數也就變得相同了,然後將原函數上移至父類
意思很簡單,就是說你看見有些函數的具體操作不同,但是幾個函數的組合操作順序是一樣的,那麼就把它們的操作順序提煉成函數放進父類。
11、以委托取代繼承
修改點:某個子類只使用父類接口的一部分,或是根本不需要繼承來的數據
做法:在子類中新建一個字段用以保存父類;調整子類函數,令它改而委托超類;然後去掉兩者之間的繼承關系
動機:隨著需求的變化,一開始的繼承關系可能在慢慢變化後,你就發現父類中的許多操作並不適用於子類
Troy:這個時候你當然可以去把這些不適用子類的方法去搞到另一個子類裡,但是如果做不到,那麼就將父類對象作為子類的一個對象吧,去掉繼承關系,這在設計模式裡面貌似可以叫組合模式
12、以繼承取代委托(看吧看吧,總是有相反的兩個重構操作出現)
修改點:你在兩個類之間使用委托關系,並經常為整個接口編寫許多極簡單的委托函數
做法:讓委托類繼承受托類
兩條告誡:
1.如果你並沒有使用受托類的所有函數。那麼你可能不需要使用此方法,你可以去去除中間人,用客戶端直接調用受托類,也可以把委托類和受托類之間提煉出一個超類,當然也可以提取接口
2.受托對象被不止一個其他對象共享,而且受托對象是可變的。那麼這種情況下你也不應該用此重構,因為這樣就無法共享數據了,數據共享是委托關系承擔的一種責任,你無法把它轉化為繼承關系。如果受托對象不可變你才能這麼做。