Time of Update: 2018-12-07
你手上一個條件運算式,它根據物件類型的不同而選擇不同的行為。將這個條件運算式的每個分支放進一個子類的覆寫函數中,然後將原始函式宣告為抽象函數。動機:多態的最根本的好處是:如果你需要根據對象的不同類型而採取不同的行為,多態使你不必編寫某些的條件運算式。 正因為有了多態,所以你會發現:“類型嗎的switch語句”以及 ”基於類型名稱的if-then-else語句“在物件導向程式中很少出現。
Time of Update: 2018-12-07
你需要為服務類提供一些額外函數,但你無法修改這個類。建立一個新類,使它包含這些額外函數。讓這個擴充品成為源類的子類或封裝類。動機:類的作者無法預知未來,他們常常沒能為你預先準備一些有用的函數。如果你可能修改源碼,最後的辦法就是直接加入自己需要的函數。但你經常無法修改源碼。如果只需要一兩個函數,你可以使用 Introduce Foreign Method
Time of Update: 2018-12-07
有時你會看到這樣的對象:其內某個執行個體變數僅為某種特定情況而設。這樣的代碼讓人不易理解,因為你通常認為對象在所有時候都需要它的所有變數。在變數未被使用的情況下猜測當初設定目的,會讓你發瘋。 請使用Extract Class (提煉類)給這些變數創造一個家,然後把所有和這些變數相關的代碼都放進這個新家,也許你還可以使用 Introduce Null Object (引入Null 對象)在變數不合法的情況下建立一個null對象,從而避免寫出條件式代碼。
Time of Update: 2018-12-07
你有一個大型函數,其中對局部變數的使用使你無法採用 Extract Method (提煉函數)。將這個大型函數放進一個單獨對象中,如此一來局部變數就成了對象內的欄位。然後你可以在同一個對象中將這個大型函數分解為多個小型函數。 動機:局部變數的存在會增加函數分解的難度。如果一個函數之中局部變數泛濫,那麼想分解這個函數是非常困難的。Replace Temp with Query
Time of Update: 2018-12-07
[導讀][設計模式整理筆記 一] 基礎知識[設計模式整理筆記 二] 簡單原廠模式(Simple Factory)[設計模式整理筆記 三] 原廠模式(Factory)[設計模式整理筆記 四] 抽象原廠模式(Abstract Factory)[設計模式整理筆記 五] 建立者模式(Builder)[設計模式整理筆記 六] 原廠模式與建立者模式總結[設計模式整理筆記 七] 原型模式(ProtoType)[設計模式整理筆記 八] 單例模式(Singleton)[設計模式整理筆記
Time of Update: 2018-12-07
類中的某些特性只被某些執行個體用到。建立一個子類,將上面所說的那一部分特性移到子類中。動機:使用Extract Subclass (提煉子類)的主要動機是:你發現類中的某些行為只被一部分執行個體用到,其他執行個體不需要它們。有時候這種行為上的差異是通過類型碼區分的,此時你可以使用Replace Type Code with Subclass (以子類取代類型碼)或Replace Type Code with State/Strategy
Time of Update: 2018-12-07
類中的某個欄位應該在對象建立時被設值,然後就不再改變。去掉該欄位的所有設值函數。動機:如果你為某個欄位提供了設值函數,這就暗示這個欄位值可以被改變。如果你不希望在對象建立之後此欄位還有機會被改變,那就不要為它提供設值函數。這樣你的意圖會更加清晰,並且可以排除其值被修改的可能性。 如果你保留了間接訪問變數的方法,就可能經常有程式員盲目使用它們。這些人甚至會在建構函式中使用設值函數。做法:1、檢查設值函數被使用方式,看它是否只是被建構函式調用,或者被建構函式所調用的另一個函數調用。
Time of Update: 2018-12-07
類之中有一個數實值型別碼,但它並不影響類的行為。以一個新的類替換該數實值型別碼。動機:在以C為基礎的程式設計語言中,類型碼或枚舉值很常見。如果帶著一個有意義的符號名,類型碼的可讀性還不錯。問題在於,符號名終究只是個別名,編譯器看見的、進行類型檢驗的,還是背後那個數值。任何接受類型碼作為參數的函數,所期望的實際上是一個數值,無法強制使用符號名。這會大大降低代碼的可讀性,從而成為bug之源。
Time of Update: 2018-12-07
你需要再三檢查某對象是否為null。將null值替換為null對象。動機:多態的最根本好處在於:你不必再向對象詢問“你是什麼類型”而後根據得到的答案調用對象的某個行為-你只管調用該行為就是了,其他的一切多態機制會為你安排妥當。當某個欄位內容是null時,多態可扮演另一個較不直觀的用途。做法:1、為源類建立一個子類,使其行為就像是源類的null版本。在源類和null子類中都加上IsNull()函數,前者的IsNull()應該返回false,後者的IsNull()返回true。
Time of Update: 2018-12-07
如果你看到使用者向一個對象請求另一個對象,然後再向後者請求另一個對象,然後再請求另一個對象……這就是訊息鏈。實際代碼中你看到的可能是一長串getThis()或一長串臨時變數。採取這種方式,意味客戶代碼將與尋找過程中的導航緊密耦合。一旦對象間關係發生任何變化,用戶端就不得不做出相應的修改。 這時候應該使用 Hide Delegate (隱藏委託關係)。你可以在訊息鏈的不同位置進行這種重構。理論上可以重構訊息鏈上任何對象,但這麼做往往會把一系列對象都變成Middle
Time of Update: 2018-12-07
你的程式有某個臨時變數被賦值超過一次,它既不是迴圈變數,也不被用於收集計算結果。針對每次賦值,創造一個獨立、對應的臨時變數double temp = 2 + (_height + _width); Console.WriteLine(temp); temp = _height * _width; Console.WriteLine(temp); const double perimeter = 2 + (_height + _
Time of Update: 2018-12-07
對象調用某個函數,並將所得結果作為參數,傳遞給另一個函數。而接受該參數的函數本身也能夠調用前一個函數。讓參數接受者去除該項參數,並直接調用前一個函數。動機:如果函數可以通過其他途徑獲得參數值,那麼它就不應該通過參數取得該值。過長的參數列會增加程式閱讀者的理解難度,因此應該儘可能縮短參數列的長度。
Time of Update: 2018-12-07
有一個函數返回一個集合。讓這個函數返回該集合的一個唯讀副本,並在這個類中提供添加/移除集合元素的函數。動機:我們常常會在一個類中使用集合來儲存一組執行個體。這樣的類通常也會提供針對該集合的取值/設值函數。
Time of Update: 2018-12-07
函數中的條件邏輯使人難以看清正常的執行途徑。使用衛語句表現所有特殊情況。動機:條件運算式通常有2種表現形式。第一:所有分支都屬於正常行為。第二:條件運算式提供的答案中只有一種是正常行為,其他都是不常見的情況。 這2類條件運算式有不同的用途。如果2條分支都是正常行為,就應該使用形如if…..else…..的條件運算式;如果某個條件極其罕見,就應該單獨檢查該條件,並在該條件為真時立刻從函數中返回。這樣的單獨檢查常常被稱為“衛語句”。 Replace Nested
Time of Update: 2018-12-07
你直接存取一個欄位,但與欄位之間的耦合關係逐漸層得笨拙。為這個欄位建立取值/設值函數,並且只以這些函數來訪問欄位。 間接訪問變數的好處是,子類可以通過覆寫一個函數而改變擷取資料的途徑;它還支援更靈活的資料管理方式,例如延遲初始化。 如果你想訪問超類中的一個欄位,卻又想子類中將對這個變數的訪問改為一個計算後的值,這就是使用Self Encapsulate Field
Time of Update: 2018-12-07
如果你的某個抽象類別其實沒有太大作用,請運用 Collapse Hierarch (摺疊繼承體系)。不必要的委託可運用 Inline Class (將類內聯化)除掉。如果函數的某些參數未被用上,可對它實施 Remove Parameter (移除參數)。如果函數名稱帶有多餘的抽象意味,應該對它實施Rename Method (函數改名) 如果函數或類的唯一使用者是測試案例,這就飄出了壞味道 夸夸其談未來性(Speculative Generality)。
Time of Update: 2018-12-07
在一系列布林運算式中,某個變數帶有“控制標記’的作用。以break或return語句取代控制標記。動機:在一系列條件運算式中,常常會看到用以判斷何時停止條件檢查的控制標記。這樣的標記帶來的麻煩超過了它所帶來的便利。人們之所以會使用這樣的控制標記,因為結構化編程原則告訴他們:每個子程式只能有一個入口和出口。“單一出口“原則會讓你在代碼中加入讓人討厭的控制標記,大大降低條件運算式的可讀性。這就是程式設計語言提供break和continue語句的原因:用它們跳出複雜的條件陳述式。去掉控制標記所產生的
Time of Update: 2018-12-07
[導讀][設計模式整理筆記 一] 基礎知識[設計模式整理筆記 二] 簡單原廠模式(Simple Factory)[設計模式整理筆記 三] 原廠模式(Factory)[設計模式整理筆記 四] 抽象原廠模式(Abstract Factory)[設計模式整理筆記 五] 建立者模式(Builder)[設計模式整理筆記 六] 原廠模式與建立者模式總結[設計模式整理筆記 七] 原型模式(ProtoType)[設計模式整理筆記 八] 單例模式(Singleton)[設計模式整理筆記
Time of Update: 2018-12-07
[導讀][設計模式整理筆記 一] 基礎知識[設計模式整理筆記 二] 簡單原廠模式(Simple Factory)[設計模式整理筆記 三] 原廠模式(Factory)[設計模式整理筆記 四] 抽象原廠模式(Abstract Factory)[設計模式整理筆記 五] 建立者模式(Builder)[設計模式整理筆記 六] 原廠模式與建立者模式總結[設計模式整理筆記 七] 原型模式(ProtoType)[設計模式整理筆記 八] 單例模式(Singleton)[設計模式整理筆記
Time of Update: 2018-12-07
你需要面對傳統編程環境中的記錄結構。為該記錄建立一個“啞”資料對象。動機:記錄型結構是許多編程環境的共同性質。有一些理由使它們被帶進物件導向程式之中:你可能面對的是一個遺留程式,也可能需要通過一個傳統API來與記錄結構交流,或是處理從資料庫讀出的記錄。這些時候你就有必要建立一個介面類,用以處理這些外來資料。最簡單的做法就是先建立一個看起來類似外部記錄的類,以便日後將某些欄位和函數搬移到這個類中。一個不太常見但非常令人注目的情況是:數組中的每個位置上的元素都有特定含義,這種情況下應該使用