第十一章 處理概括關係
有一批重構手法專門用於處理類的概括關係(generalization,即繼承關係),其中主要是將函式上下移動於繼承體系之中。
1、上移字段(pull up field)
判斷若干字段是否重複,唯一的辦法就是觀察函式如何使用它們。如果它們被函式使用的方式很相似,你就可以將它們歸納到超類去。本項重構從兩方面減少重複:首先它去除了重複的資料宣告;其次它使你可以將使用該字段的行為從子類移至超類,從而去除重複的行為。
2、上移函式(pull up method)
避免重複是很重要的!重複只會成為錯誤的滋生地。無論何時,只要系統之內出現重複,你就會面臨「修改其中一處卻未能修改另乙個」的風險。上移函式(pull up method)是一項很自然的重構。
3、建構函式本體上移(pull up constructor body)
本項重構手法用於去掉建構函式中的重複**。
4、下移函式(pull down method)
如果超類(基類)中的某個函式只與部分子類有關,那麼我們應該將該函式從超類(基類)中下移至特定的子類中(即需要這個特性的子類)。當然,如果你想通過基類物件訪問該函式,為了順利進行,你需要在超類(基類)中將該函式宣告為虛函式(virtual),並提供乙個預設的實現(或空實現,但不能為純虛函式)。
5、下移字段(pull down field)
如果超類(基類)中的某個欄位只被部分子類用到,那麼就應該將這個字段移至哪些需要這個欄位的子類中去。
6、提煉子類(extract subclass)
如果類中的某些特性只被某些例項用到,這是需要「提煉子類」訊號。新建乙個類,將上面所說的那一部分特性移到子類中。
extract class 和 extract subclass 其實就是「委託」和「繼承」的抉擇。如果乙個類承擔了超過乙個職責,則應該使用提煉類(extract class),將其中的部分責任委託給新提煉的類去完成。如果乙個類的有些例項用不到它的所有特性,則應該提煉出乙個子類(extract subclass),並將這部分特性搬移到新提煉的子類中去。
7、提煉超類(extract superclass)
提煉超(基)類。如果兩個類有相似特性,那麼應該將這些相似的特性提煉到乙個基類中。 重複**是系統中最糟糕的東西!如果你在不同地方做同一件事情,一旦需要修改那些動作,你就得平白做更多的修改。
8、提煉介面(extract inte***ce)
c++多重繼承的替代方案。
9、摺疊(合併)繼承體系(collapse hierarchy)
重構不僅會建立繼承體系,也可能會摺疊(去除)繼承體系。如果我們發現在乙個繼承體系中,某個子類並未帶來該有的價值,我們應該果斷移除它。
10、塑造模板函式(form template method)
塑造模板函式其實就是「定義好處理某種事情的具體步驟(或演算法的骨架)」,儘管這些具體步驟的細節可能不同,但這些不同可以通過多型來實現。
11、以委託取代繼承(replace inheritance with delegation)
我們經常糾結於是使用「繼承」還是使用「委託」?通常,如果某個子類只使用超類介面中的一部分,或者根本不需要繼承而來的資料,這種情況使用委託會更合適。
很多時候,你一開始繼承了乙個類,隨後你發現基類中的許多操作並不是真正適用於子類。這種情況下,你所擁有的介面並未真正反映出子類的功能。
你可以選擇容忍,因為這種情況通常並不會影響你實現功能。但是,這樣的**所傳達的資訊與你的意圖南轅北撤-----這是一種混淆,我們應該將其去除。
如果以委託取代繼承,你可以更清楚的表明你的意圖:你只需要受託類的一部分功能。介面中的哪一部分應該被使用,哪一部分應該被忽略,完全由你主導控制。當然,這樣做也是有成本的,即你需要額外的編寫出委託函式,但這通常不是問題,因為編寫這樣的委託函式極其簡單。
12、以繼承取代委託(replace delegation with inheritance)
物件導向程式設計中有一條很經典的原則是:優先使用委託而不是繼承。這是因為繼承往往意味著緊耦合,而委託通常能帶來松耦合的系統。但是,有時你也會因為過度信任委託而出錯。例如,如果你發現自已需要使用委託類的所有函式,並且費了很大力氣編寫所有極簡的委託函式,那麼你應該實施本項重構。
當然,我們說過:優先使用委託而不是繼承。所以,在使用本項重構之前,有兩條告誡需要牢記於心:
首先,如果你並沒有使用受託類的所有函式,那麼就不要實施本項重構,因為子類應該總是遵循基類的介面(黎克特制替換原則)。就算過多的委託函式讓你煩心,你仍然有別的選擇,還記得「移除中間人(remove middle man)」那項重構嗎?你可以直接返回受託物件給客戶端,讓客戶**自己去呼叫需要的函式,從而可以免除你編寫眾多委託函式的麻煩。
其次,如果受託物件被不止乙個其他物件共享,而且受託物件是可變的。那麼此時你也應該停止本項重構。資料共享是必須由委託關係承擔的一種責任,你無法把它轉給繼承關係。當然,如果僅僅只是資料共享,而資料物件是不可變的,那麼我們可以複製物件達到資料共享的目的。
第十一章 讀書筆記
第十一章 linux驅動程式中的 併發控制 併發 concurrency 指的是多個執行單元同時 並行被執行。而併發的執行單元對共享資 源 如硬體資摞 程式中的全域性變數 靜態變數等 的訪問很容易導致競態條件 race conditions 自旋鎖並不關心鎖定的 臨界區究竟是怎樣的操作,不管是讀還是...
第十一章讀書筆記
併發 concurrency 指的是多個執行單元同時 並行被執行。而併發的執行單元對共享資 源 如硬體資摞 程式中的全域性變數 靜態變數等 的訪問很容易導致競態條件 race conditions 例如,有乙個裝置檔案。程序 a 向該個裝置檔案寫入 1000 個 a飛而程序 b 向 裝置檔案寫入了 ...
讀書筆記 第十一章 C in depth
思考 11 2 from user in sampledata.allusers select user 轉譯 sampledata.allusers.select user user 範圍變數都可以是隱式型別。cast,oftype將飛型別化序列轉化為強型別。遇到不匹配型別,cast報錯,ofty...