1. 程式人生 > 實用技巧 >第10章 簡化函式呼叫

第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(int
arg) { 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];
}