代码重构(五):继承关系重构规则
陸陸續(xù)續(xù)的發(fā)表了多篇關于重構的文章了,還是那句話,重構是一個項目迭代開發(fā)中必不可少的一個階段。其實重構伴隨著你的項目的整個階段。在前幾篇關于重構的文章中我們談到了函數(shù)的重構、類的重構、數(shù)據(jù)的重構以及條件表達式的重構,那么今天咱們就來聊聊繼承關系的重構。當然還是延續(xù)前幾篇博客的風格,我們在博客中的代碼實例依然使用Swift語言來實現(xiàn),當然還是那句話,使用什么語言無所謂,關鍵是看重構的場景以及重構的思想。
“重構”不僅僅可以改善你既有的代碼設計,還可以改變你組織代碼的思路,使你的程序在設計之初就趨于合理化,利于程序的擴充。重構往往伴隨著設計模式的使用,在重構系列的博客結束后,我想系統(tǒng)的給大家分享一下關于設計模式的東西。當然是結合著各種實例。所謂一名Coder,重構和設計模式是必須涉獵的部分,因為這兩者可以讓你寫出更漂亮的代碼,當然要想真正的掌握設計模式以及各種重構手法,還得結合不同的實例來進行實踐。理論固然重要,但是要想將理論的東西變成你自己的,還必須將理論付諸實踐。廢話少說,進入今天的主題。
一.Pull Up Field (字段上移) &?Pull Down Field (字段下移)
字段上移與字段下移是相對的,也是我們之前所說的“凡事都有其兩面性”,我們要辯證的去看待。我們只對Pull Up Field (字段上移)?這個規(guī)則做討論,那么關于Pull Down Field (字段下移)我們不做過多的討論,因為這兩條規(guī)則是相反的,理解一條后,把這條規(guī)則反過來就是我們要理解的另一條規(guī)則。這樣說起來,還是比“舉一反三”要容易的多。
下方這個實例是為了解釋“字段上移”所實現(xiàn)的一個Demo。當然Demo看上去不僅簡單而且是有些夸張的,不過說明字段上移這個規(guī)則是完全足夠了的。比如我們有一個父類為MySuperClass,我們有一個子類SubClass1,而在SubClass1中有一個字段父類是沒有的。因為后期需求迭代或者需求變更,我們需要再創(chuàng)建一個SubClass1的兄弟類,就是下方的SubClass2。在SubClass2中與SubClass1中存在相同的字段,那就是var a = 0。
? ??
?
?在上述情況下,就需要使用到我們的“字段上移”的規(guī)則。也就是說將子類中相同的字段移到父類中。在該實例中就是講var a = 0?移到父類中。重構后的代碼如下所示:
而將“Pull Down Field (字段下移)”正好與上面的情況相反。也就是父類中有某些字段,但是這些字段只有在少數(shù)子類中使用到,在這種情況下我們需要將這個字段移到相應的子類中即可。除了Pull Up Field (字段上移) &?Pull Down Field (字段下移)?這兩個規(guī)則外,Pull Up Method (將函數(shù)上移) 和?Pull Down Method (將函數(shù)下移)這兩個規(guī)則與上述情況類似。就是將上面的字段改成函數(shù),有時候不僅字段會出現(xiàn)上述情況,函數(shù)也會出現(xiàn)上述情況,需要我們進行移動。因為使用場景類似,再次就不做過多的贅述了。
?
二、Extract Subclass (提煉子類)
這種情況下用的還是比較多的,當類中的某些方法只有在特定的類的實例中才會使用到,此時我們就需要提煉出一個子類,將該方法放到相應的子類中。這樣一來我們的每個類的職責更為單一,這也就是我們常說的“單一職責”。
在下方示例中,CustomerBook是一個圖書消費者的類。其中customeCharge()方法是普通用戶計算消費金額所需的方法,而vipCharge()方法是VIP用戶調用的方法,在內部vipCharge()需要調用customeCharege()方法。但是對外部而言,vipCharge()方法只有VIP用戶才會用到,在這種情況下我們就需要使用“Extract Subclass (提煉子類)”規(guī)則對VIP進行提煉。
? ??
?
具體做法是我們需要提煉出一個子類,也就是說將VIP用戶作為普通用戶的子類,然后將只有VIP用戶才調用的方法放到我們的VIP子類中。這樣一來層次更加明確,每個類的職責更為單一。上述示例重構后的結果如下所示。
? ?
與“提煉子類”規(guī)則相對應的是“Collapse Hierarchy (折疊繼承關系)”。一句話來概括:就是當你的父類與子類差別不大時,我們就可以將子類與父類進行合并。將上面的示例翻轉就是“Collapse Hierarchy (折疊繼承關系)”規(guī)則的示例,再次就不做過多的贅述了。
?
三、Form Template Method (構造模板函數(shù))
Form Template Method (構造模板函數(shù))這一規(guī)則還是比較實用的。先說模板,“模板”其實就是框架,沒有具體的實現(xiàn)細節(jié),只有固定不變的步驟,可以說模板不關心具體的細節(jié)。舉個栗子,像前段時間比較火的“秘密花園”,那些沒有顏色的線條就是模板,如果一些人獲取的是同一本秘密花園,那么說明每個人所獲取的模板是相同的。但是每個人對每塊的區(qū)域所圖的顏色又有差異,這就是實現(xiàn)細節(jié)的不同。
言歸正傳,當兩個兄弟類中的兩個函數(shù)中的實現(xiàn)步驟大致一直,但是具體細節(jié)不同。在這種情況下,我們就可以將大體的步驟提取成模板,放到父類中,而具體細節(jié)由各自的子類來實現(xiàn)。具體實現(xiàn)請看下方的類,在Subclass1和Subclass2中的calculate()方法中的大體步驟是相同的,就是對兩個值相加,然后返回這兩個值的和。但是具體細節(jié)不同,可以看出兩個相加值的具體計算方式不同。
??
?
在上述情況下我們就可以使用“Form Template Method (構造模板函數(shù))”規(guī)則將相同的計算流程進行提取,也就是構造我們的模板函數(shù)。將模板函數(shù)放到兩個類的父類中,然后在相應的子類中只給出實現(xiàn)細節(jié)即可。下方代碼段是重構后的代碼,父類中多出的方法就是我們提取的模板函數(shù),而子類中只給出相應的實現(xiàn)細節(jié)即可。
??
?
四、以委托取代繼承(Replace Inheritance with Delegation)
有時候我們?yōu)橐恍╊悇?chuàng)建子類后,發(fā)現(xiàn)子類只使用了父類的部分方法,而且沒有繼承或者部分繼承了父類的數(shù)據(jù)。在這種情況下我們就可以將這種繼承關系修改成委托的關系。具體做法就是修改這種繼承關系,在原有子類中添加父類的對象字段,在子類中創(chuàng)建相應的方法,在方法中使用委托對象來調用原始父類中相應的方法。
下方示例是我們假想出來的,但是說明該規(guī)則是綽綽有余了。我們假設SubClass01類中只會用到SuperClass01中的display()方法,而沒有繼承父類中的數(shù)據(jù)。在下方示例中是繼承關系,在這種情況下我們需要將其轉換成委托關系。
??
下方是我們重構后的代碼,在下方代碼中我們去除了之前的繼承關系。并在子類中創(chuàng)建了一個之前父類的代理對象,并且創(chuàng)建了一個相應的方法,在該新建的方法中通過代理對象來調用相應的方法。具體如下所示。
??
上述規(guī)則與以繼承取代委托(Replace Delegation with Inheritance)原則相對于,使用情況與上述相反,再次就不做過多的贅述了。
幾天博客就先到這兒,內容比較簡單,但是還是比較重要的。
總結
以上是生活随笔為你收集整理的代码重构(五):继承关系重构规则的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 20135337朱荟潼 Linux第八周
- 下一篇: startActivities的使用