第10章 簡化函式呼叫
本章將介紹幾個使介面變得更簡潔易用的重構手法。
函式改名(Rename Method)
1.概念:
函式的名稱未能揭示函式的用途,則修改函式名稱。emmmm...通俗易懂。
新增引數(Add Parameter)
1.概念:
某個函式需要從呼叫端得到更多的資訊,為此函式新增一個物件引數,讓該物件帶進函式所需資訊。
2動機:
你必須修改一個函式,而修改後的函式需要一些過去沒有的資訊,因此你需要給該函式新增一個引數。
移除引數(Remove Parameter)
1.概念:
函式本體不再需要某個引數,將該引數去除。
2.動機:
引數代表函式所需要的資訊,函式呼叫者必須為每一個引數操心該傳什麼東西進去,於是有了多餘的引數,就應該去掉,而不是想著以後可能會用且目前沒錯就不管了。
將查詢函式和修改函式分離(Separate Query from Modifier)
1.概念;
某個函式既返回物件狀態值,又修改物件狀態,則建立兩個不同的函式,其中一個負責查詢,另一個負責修改。
單一 職責原則吧。
令函式攜帶引數(Parameterize Method)
1.概念:
若干函式做了類似的工作,但在函式本體中卻包含了不同的值。則建立單一函式,以引數表達那些不同的值。
2.動機:
你可能發現有著這樣兩個函式:它們做著類似的工作,但只因少數幾個值致使行為略有不同。這時就可以將這兩個各自分離的函式統一起來,並通過引數處理。
以明確函式取代引數(Replace Parameter with Explicit Methods)
1.概念:
你有一個函式,其中完全取決於引數值而採取不同的行為。則針對該引數的每一個可能值,建立一個獨立函式。
原來下面常用的這個是優勝劣汰,自然選擇後的結果:
//改變前 void setValue(String name, int value) { if (name.equals("height")) { height = value; return; } if (name.equals.("width")) { width = value; return; } } //改變後 void setHeight(intarg) { height = arg; } void setWidth(int arg) { width = arg; }
保持物件完整(Preserve Whole Object)
1.概念:
你從某個物件中取出若干值,將它們作為某一次函式呼叫時的引數,則改為傳遞整個物件。
即:將傳入引數封裝成物件傳入。
以函式取代引數(Replace Parameter with Methods)
1.概念:
物件呼叫某個函式,並將所得結果作為引數,傳遞給另一個函式,而接受該引數的函式本身也能呼叫前一個函式。
2.動機:
如果函式可以通過其他途徑獲得引數值,則它不應該通過引數獲得該值。
//修改前 int basePrice = A * B; discountLevel = getDiscountLevel(); double finalPrice = discountedPrice(basePrice, discountLevel); //修改後(已經是程式設計習慣了的,注意不要犯錯犯回去就好) int basePrice = A * B; double finalPrice = discountedPrice(basePrice);
3.壞味道:
過長引數列會增加程式閱讀者的理解難度,因此我們應該儘可能縮短引數列的長度。
引入引數物件(Introduce Parameter Object)
1.概念:
某些引數總是很自然地同時出現,則以一個物件取代這些引數。
2.動機:
當一組引數總是一起被傳遞。可能有好幾個函式都使用這一組引數,這些函式可能屬於同一個類,也可能屬於不同類,這樣一組引數就是所謂的資料泥團。我們可以用物件包裝,以物件取代他們。
移除設值函式(Remove Setting Method)
1.概念:
類中的某個欄位應該在物件建立時被設值,然後就不再改變,則去掉該欄位的所有設值函式。
2.動機:
如果你不希望在物件建立後此欄位還有機會被改變,則不要給這個物件提供設值函式(同時將該欄位設為final)
隱藏函式(Hide Method)
1.概念:
有一個函式,從來沒有被其他任何類用到,則將這個函式改為private。
以工廠函式取代建構函式(Replace Constructor with Factory Method)
1.概念:
你希望在建立物件的時候不僅僅是做簡單的建構動作,則將建構函式替換為工廠函式。
略。。
封裝向下轉型(Encapsulate Downcast)
1.概念:
某個函式返回的物件,需要由函式呼叫者執行向下轉型,則向下轉型動作移到函式中。
Object lastReading() { return reading.lastElement(); } //將向下轉型移動到函式中 Reading lastReading() { return (Reading) readings.lastElement(); }
以異常取代錯誤碼(Replace Error Code with Exception)
1.概念:
某個函式返回一個特定的程式碼,用以表示某種錯誤情況,則改用異常。
int withdraw(int amount) { if (amount > balance) { return -1; } else { balance -= amount; return 0; } } //改變後 void withdraw(int amount) throws BalanceException { if (amount > balance) throw new BalanceException(); balance -= amount; }
以測試取代異常(Replace Exception with Test)
1.概念:
面對一個呼叫者可以預先檢查的條件,你丟擲了一個異常,則修改呼叫者,使他在呼叫函式前先做檢查。
//直接丟擲異常 public double getValueForPeriod(int periodNumber) { try { return ... } catch (ArrayIndexOutOfBoundsException e) { return 0; } } //先檢查,再丟擲異常 public double getValueForPeriod(int periodNumber) { if (periodNumber >= values.length) return 0; return values[periodNumber]; }