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
類中的某個欄位應該在對象建立時被設值,然後就不再改變。去掉該欄位的所有設值函數。動機:如果你為某個欄位提供了設值函數,這就暗示這個欄位值可以被改變。如果你不希望在對象建立之後此欄位還有機會被改變,那就不要為它提供設值函數。這樣你的意圖會更加清晰,並且可以排除其值被修改的可能性。 如果你保留了間接訪問變數的方法,就可能經常有程式員盲目使用它們。這些人甚至會在建構函式中使用設值函數。做法:1、檢查設值函數被使用方式,看它是否只是被建構函式調用,或者被建構函式所調用的另一個函數調用。
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
[導讀][設計模式整理筆記 一] 基礎知識[設計模式整理筆記 二] 簡單原廠模式(Simple Factory)[設計模式整理筆記 三] 原廠模式(Factory)[設計模式整理筆記 四] 抽象原廠模式(Abstract Factory)[設計模式整理筆記 五] 建立者模式(Builder)[設計模式整理筆記 六] 原廠模式與建立者模式總結[設計模式整理筆記 七] 原型模式(ProtoType)[設計模式整理筆記 八] 單例模式(Singleton)[設計模式整理筆記
Time of Update: 2018-12-07
2個類有相似特性。為這2個類建立一個超類,將相同特性移至超類。動機:重複代碼是系統中最糟糕的東西之一。如果你在不同地方做同一件事情,一旦需要修改那些動作,你就得平白做更多的修改。 重複代碼的某種形式就是:2個類以相同的方式做類似的事情,或者以不同的方式做類似的事情。對象提供了一種簡化這種情況的機制,那就是繼承。但是,在建立這些具有共通性的類之前,你往往無法發現這樣的共通性,因此常常會在具有共通性的類出現之後,再開始建立其間的繼承結構。 另一種選擇就是 Extract
Time of Update: 2018-12-07
有一個函數,從來沒有被其他任何類用到。將這個函數修改為private。動機:重構往往促使你修改函數的可見度。提高函數可見度的情況很容易想象:另一個類需要用到某個函數,因此你必須提高該函數的可見度。但是要指出一個函數的可見度是否過高,就稍微困難一些。理想狀態下,你可以使用工具檢查所有函數,指出可被隱藏起來的函數。即使沒有這樣的工具,你也應該時常進行這樣的檢查。
Time of Update: 2018-12-07
從一個類中衍生出許多彼此相等的執行個體,希望將它們替換為一個對象。將這個值對象變成引用對象。動機:在許多系統中,都可以對對象做一個有用的分類:引用對象和值對象。要在引用對象和值對象之間做選擇有時並不容易。有時候,你會從一個簡單的值對象開始,在其中儲存少量不可修改的資料。而後,你可能會希望給這個對象加入一些可修改資料,並確保對任何一個對象的修改都能影響到所引用此對象的地方。這時候你就需要將這個對象變成引用對象。做法:1、使用 Replace Constructor with Factory
Time of Update: 2018-12-07
物件導向程式的一個最明顯特徵就是:少用switch或(case)語句。從本質上說,switch語句的問題在於重複。你常會發現switch語句散佈於不同地點。如果要為它添加一個新的case子句,就必須找到所有switch語句並修改它們。物件導向中的多態概念可為此帶來優雅的解決辦法。 大多數時候,一看到switch語句,就應該考慮以多態來替換它。問題是多態該出現在哪?switch語句常常根據類型碼進行選擇,你要的是“與該類型碼相關的函數或類”,所以應該使用 Extract
Time of Update: 2018-12-07
代碼對一個 參數賦值。以一個臨時變數取代該參數的位置。 int Discount(int inputVal, int quantity, int yearTodate) { if (inputVal > 50) { inputVal -= 2; } } int Discount(int inputVal, int quantity, int
Time of Update: 2018-12-07
你直接存取一個欄位,但與欄位之間的耦合關係逐漸層得笨拙。為這個欄位建立取值/設值函數,並且只以這些函數來訪問欄位。 間接訪問變數的好處是,子類可以通過覆寫一個函數而改變擷取資料的途徑;它還支援更靈活的資料管理方式,例如延遲初始化。 如果你想訪問超類中的一個欄位,卻又想子類中將對這個變數的訪問改為一個計算後的值,這就是使用Self Encapsulate Field
Time of Update: 2018-12-07
[導讀][設計模式整理筆記 一] 基礎知識[設計模式整理筆記 二] 簡單原廠模式(Simple Factory)[設計模式整理筆記 三] 原廠模式(Factory)[設計模式整理筆記 四] 抽象原廠模式(Abstract Factory)[設計模式整理筆記 五] 建立者模式(Builder)[設計模式整理筆記 六] 原廠模式與建立者模式總結[設計模式整理筆記 七] 原型模式(ProtoType)[設計模式整理筆記 八] 單例模式(Singleton)[設計模式整理筆記
Time of Update: 2018-12-07
若干客戶使用類介面中的同一子集,或者2個類的介面部分相同。將相同的子集提煉到一個獨立介面中。動機:類之間彼此互用的方式有若干種。“使用一個類”通常意味著用到該類的所有責任區。另一種情況是,某一組客戶只使用類責任區中的一個特定子集。再一種情況是,這個類需要與所有協助處理某些特定請求的類合作。 對於後2種情況,將真正用到的這部分責任分離出來通常很有意義,因為這樣可以使系統的用法更清晰,同時也更容易看清系統的責任劃分。如果新的類需要支援上述子集,也比較能夠看清子集內有些什麼東西。
Time of Update: 2018-12-07
你希望在建立對象時不僅僅是做簡單的建構動作。將建構函式替換為工廠函數。動機:就是在派生子類的過程中以工廠函數取代類型碼。你可能常常需要根據類型碼建立相應的對象,現在,建立名單中還得加上子類,那些子類也是根據類型碼來建立。然而由於建構函式只能返回單一類型的對象,因此你需要將建構函式替換為工廠函數。 此外,如果建構函式的功能不能滿足你的需要,也可以使用工廠函數代替它。工廠函數也是Change Value to Reference
Time of Update: 2018-12-07
函數的名稱未能揭示函數的用途。修改函數名稱。動機:大力提倡的一種編程風格是:將複雜的處理分解成小函數。但是,如果做得不好,這會使你費盡周折卻弄不清楚這些小函數各自的用途。要避免這種麻煩,關鍵就在於給函數起一個好名稱。函數的名稱應該準確表達它的用途。給函數命名有一個好辦法:首先考慮應該給這個函數寫上一句怎樣的注釋,然後想辦法將注釋變成函數名稱。
Time of Update: 2018-12-07
你有一個引用對象,很小且不可變,而且不易管理。將它變成一個值對象。動機:要在引用對象和值對象之間做選擇,有時並不容易。做出選擇後,你常會需要一條回頭路, 如果引用對象開始變得難以使用,也許就應該將它改為值對象。引用對象必須被某種方式控制,你總是必須向其控制者請求適當的引用對象。它們可能造成記憶體地區之間錯綜複雜的關聯。在分布式和並發系統中,不可變的值對象特別有用,因為你無需考慮它們的同步問題。