有時候,當你遇到一個大型函數,裏面的臨時變量和參數多的讓你以爲根本沒法進行Extract Method。重構中也大力的推薦短小函數的好處,它所帶來的解釋性,複用性讓你收益無窮。但若是你遇到上種狀況,你可能會天真的覺得我只要適當的進行Replace Temp with Query,就能夠把這種現象給化解。但狀況每每事與願違,不能達到你所理想的高度。這個時候你須要用到重構中的殺手鐗--Replace Method with Method Object,這個手法出自Kent Beck [Beck]。html
簡單的說,這個重構會把源函數內的全部局部變量的參數都變成Method Object的字段。而後由於是字段,因此就不存在臨時變量這個限制,你就能夠輕輕鬆鬆的對新對象的新函數進行Extract Method將原來的大型函數進行輕鬆拆解。函數
作法:this
完成這些以後,你就能夠對新類中的compute()函數進行大刀闊斧的改造了。spa
例子:code
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; return importantValue3 - 2 * importantValue1; }
這是咱們的原函數,能夠看到,參數和臨時變量很是多,很是難以進行Extract Method。因此是時候用出咱們的殺手鐗,首先按照『作法』,咱們新建一個新類,而後將這個函數的參數和臨時變量都變成他的字段。htm
class Gamma { private: const Account *m_account; int inputVal; int quantity; int yearToDate; int importantValue1; int importantValue2; int importantValue3; };
爲了保證重構的小步進行,這裏咱們不對字段變量進行任何更名,這樣有其何處,當你將原函數的實現搬過來的時候,你暫時不須要進行任何修改。對象
接下來咱們進行構造函數的聲明,注意:這個時候你只須要將原函數的所在對象和所需參數看成構造函數參數便可,不須要全部的臨時變量。blog
public: Gamma(Account *account, int inputValArg, int quantityArg, int yearToDateArg) : m_account(account), inputVal(inputValArg), quantity(quantityArg), yearToDate(yearToDateArg) { }
接下來,咱們聲明compute()函數,而且將原函數的實現搬過來,講裏面的聲明刪除,由於已是新類的字段了,而後將對源對象自己的函數調用替換成對字段的調用,完整實現以下get
class Gamma { public: Gamma(Account *account, int inputValArg, int quantityArg, int yearToDateArg) : m_account(account), inputVal(inputValArg), quantity(quantityArg), yearToDate(yearToDateArg) { } int compute() { importantValue1 = (inputVal * quantity) + m_account->delta(); importantValue2 = (inputVal * yearToDate) + 100; if ((yearToDate - importantValue1) > 100) importantValue2 -= 20; importantValue3 = importantValue2 * 7; return importantValue3 - 2 * importantValue1; } private: const Account *m_account; int inputVal; int quantity; int yearToDate; int importantValue1; int importantValue2; int importantValue3; };
注意,其中的delta()函數,此時已經變成了m_account->delta(),而且全部變量的聲明都已經被刪除。input
完成了這一步以後,其實咱們已經結束了本次重構手法,但還沒完,咱們之因此運用Replace Method with Method Object就是爲了更好的進行Extract Method,因此接下來,咱們就能夠輕輕鬆鬆對新類新函數進行重構,好比
class Gamma... int compute() { importantValue1 = (inputVal * quantity) + m_account->delta(); importantValue2 = (inputVal * yearToDate) + 100; importThing(); return importantValue3 - 2 * importantValue1; } private: void importThing() { if ((yearToDate - importantValue1) > 100) importantValue2 -= 20; }
這樣,咱們就輕鬆作到了對compute()函數的無參化的Extract Method,整個實現更加簡潔,不須要去擔憂參數傳遞的問題。最後咱們來看下最終被咱們重構以後原函數的內容
class Account... int gamma(int inputVal, int quantity, int yearToDate) { return new Gamma(this, inputVal, quantity, yearToDate).compute(); }
原函數的實現變的異常簡潔以外,咱們能夠對新類函數進行各類重構,最後就能夠獲得一個很好的重構效果。