有一個大型函數,其中對局部變量的使用使你沒法採用Extract Method。將這個函數放進一個單獨對象中,如此一來局部變量就成了對象內的字段。而後能夠在同一個對象中將這個大型函數分解爲多個小型函數。java
局部變量的存在會增長函數分解的難度。若是一個函數之中局部變量氾濫成災,那麼想分解這個函數是很是困難的。Replace Temp with Query能夠幫助減輕這一負擔,可是有時候根本沒法拆解一個須要拆解的函數。這種狀況下,就要用到函數對象(method object)這一法寶。函數
Replace Method with Method Object 會將全部局部變量都變成函數對象的字段而後能夠對這個新對象使用Extract Method 創造出新函數,從而將本來的大型函數拆解變短。this
1. 創建一個新類,根據待處理函數的用途,爲這個類命名spa
2. 在新類中創建一個final字段,用以保存原先大型函數所在的對象。咱們將這個字段稱爲「源對象」。同時,針對原函數的每一個臨時變量和每一個參數,在新類中創建一個對應的字段保存之。code
3.在新類中創建一個構造函數,接受源對象及原函數的全部參數做爲參數。對象
4.在新類中創建一個compute () 函數。input
5. 將原函數的代碼複製到compute () 函數中。若是須要調用源對象的任何函數,請經過源對象字段調用。it
6. 編譯io
7. 將舊函數的函數本體替換爲這樣一條語句:「建立上述新類的一個新對象,然後調用其中的compute () 函數」。編譯
public class Account { int gamma( int inputVal, int quantity, int yearToDate ) { int importantValue1 = ( inputVal * quantity ) + delta(); int importantValue2 = ( inputVal * yearToDate ) + 100; if( ( yearToDate - importantValue1 ) > 100 ) { importantValue2 -= 20; } int importantValue3 = importantValue2 * 7; //and so on. return importantValue3 - 2 * importantValue1; } }
爲了把這個函數變成一個函數對象,咱們須要首先聲明一個新類。在此新類中咱們應該提供一個final字段用以保存源對象;對於函數的每個參數和每個臨時變量,也以一個字段逐一保存。 爲了保持小步前進,咱們暫時先保留這些字段的原名。而後,加入一個構造函數
class Gamma{ private final Account account; private int inputVal; private int quantity; private int yearToDate; private int importantValue1; private int importantValue2; private int importantValue3; Gamma( Account source, int inputValArg, int quantityArg, int yearToDateArg ) { account = source; inputVal = inputValArg; quantity = quantityArg; yearToDate = yearToDateArg; } }
如今能夠把本來的函數搬到compute() 了。函數中任何調用Account類的地方,咱們都必須改而使用account字段。
int compute() { int importantValue1 = ( inputVal * quantity ) + account.delta(); int importantValue2 = ( inputVal * yearToDate ) + 100; if( ( yearToDate - importantValue1 ) > 100 ) { importantValue2 -= 20; } int importantValue3 = importantValue2 * 7; //and so on. return importantValue3 - 2 * importantValue1; }
而後,修改舊函數,讓它將工做委託給剛完成的這個函數對象。
int gamma( int inputVal, int quantity, int yearToDate ) { return new Gamma(this, inputVal, quantity, yearToDate).compute(); }
這就是本項重構的基本原則。它帶來的好處是:如今咱們呢能夠輕鬆地對compute()函數採起Extract Method, 沒必要擔憂參數傳遞的問題。