文章目錄
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
- 解釋:
- 衝動前:
- 衝動後:
- 解釋:
1. Move Method (函數搬家)解釋:
如果 ClassA 的某個函數對 ClassB 有過多的依賴, 可以考慮將這個函數搬到 ClassB 中, 在 ClassA 的這個函數中直接調用 ClassB中這個函數的傳回值.
這樣做的好處是減少物件與物件之間的耦合度, 很多情況下這樣做更利於進一步的重構.
衝動前:
class EmployeeSalary{ private double baseSalary = 15000.0; public double Salary(Employee employee) { return baseSalary + 10000 / employee.Level; } // other method with baseSalary}class Employee{ public int Level { get; set; }}衝動後:
class EmployeeSalary{ private double baseSalary = 15000.0; public double Salary(Employee employee) { return employee.Salary(baseSalary); } // other method with baseSalary}class Employee{ public int Level { get; set; } public double Salary(double baseSalary) { return baseSalary + 10000 / Level; }}2. Move Field (範圍搬家)解釋:
有一天發現公司原來計算員工工資的方法不合適了, 比如不是所有的員工起薪 (baseSalary) 都是一萬五, 我想把 baseSalary 搬到 Employee 這個物件中作為員工的一個屬性.
這樣做可使程式擴充性變得更好, 最明顯的是我可以設定不同員工的起薪了.
衝動前:
class EmployeeSalary{ private double baseSalary = 15000.0; public double Salary() { double salary = baseSalary; //do some compution with salary return salary; }}衝動後:
class EmployeeSalary{ public double Salary(Employee employee) { double salary = employee.BaseSalary; //do some compution with salary return salary; }}class Employee{ public double BaseSalary { get; set; }}3. Extract Class (提煉類)解釋:
當某個物件做的事情過多, 這樣的物件往往含有大量的欄位, 屬性和方法. 應該由兩個或更多個物件來分擔這些責任, 這時需要使用 Extract Class.
衝動前:
class Employee{ public double BaseSalary { get; set; } public double Level { get; set; } public double Salary() { double salary = BaseSalary; //do some complex compution with salary return salary; }}衝動後:
class EmployeeSalary{ public double Salary(Employee employee) { double salary = employee.BaseSalary; //do some complex compution with salary return salary; }}class Employee{ public double BaseSalary { get; set; } public double Level { get; set; } public double Salary() { EmployeeSalary salary = new EmployeeSalary(); return salary.Salary(this); }}4. Inline Class (將類內聯)解釋:
Inline Class 和 Extract Class 正好相反. 當一個物件沒有做它應該做的事情, 還專門使用了另一個物件來協助它完成這個職責, 這時可以考慮使用 Inline Class.
如上面所示的例子, 如果我覺得 Employee 這個物件本身就應該實現 Salary 的計算工作, 而不是專門寫一個 Salary 的計算物件來協助它計算, 可以使用 Inline Class 將 Salary 內聯到 Employee 中去, 也就是"衝動後"的代碼重構成"衝動前"代碼的樣子.
5. Hide Delegate (隱藏委託關係)解釋:
試想這麼一個情況: 有一個 Employee 類, 這個類中含有一個部門 (Department) 屬性, 並且 Department 是一種類. 如果我想知道某職工所在部門的經理人是誰的時候, 我需要通過 xxEmployee.Department.Manger 來訪問. 但這樣做有個缺點是對於其它代碼, Department 是 public 的, 其它代碼能夠訪問到 Department 裡的其它特性. 可以在 Employee 類中寫一個 GetManger() 方法進行封裝, 在調用的時候只需要xxEmployee.GetManger() 就行了.
衝動前:
class Department{ public string Manger { get; set; }}class Employee{ public Department Department { get; set; }}衝動後:
class Department{ public string Manger { get; set; }}class Employee{ private Department Department; public string GetManger() { return Department.Manger; }}6. Remove Middle Man (幹掉中間人)解釋:
這一條與上一條 Hide Delegate 是相反的. 當我們要訪問 Department 的其它很多特性時, 我們用 Hide Delegate 寫了一條條簡單的委託訪問函數, 當這些函數多到幾乎訪問遍了 Department 裡的內容, 可以考慮使用 Remove Middle Man 方法將這些訪問函數幹掉.
如上面的例子, 就是將"衝動後"的代碼重構成"衝動前"代碼的樣子.
7. Introduce Foreign Method (引入外加函數)解釋:
Introduce Foreign Method 有很深的 C#3.0 中擴充方法的味道, 但擴充方法比 Introduce Foreign Method 好在: 擴充方法就好象是被擴充的那個類型自己的方法一樣, 而 Introduce Foreign Method 的函數還需要傳遞這個類型的參數, 但其實編譯器編譯擴充方法後還是會把參數傳進去的, 擴充方法只是一種文法糖.
它的主要目的是實現被調用的類中沒有實現的功能, 注意在進行本項重構時, 如果引入一個外加函數, 這說明這個函數本應該在被調用的類中實現. 下面舉一個簡單到不能再簡單的例子, 這個例子只是說明怎麼使用 Introduce Foreign Method, 我並不是說 Int32類型就應該有一個 NextNum 的方法 , 並且實際中多數情況下這種重構用於參考型別
衝動前:
int num = 1;//I want to get num's nextint nextNum = num + 1;
衝動後:
int num = 1;int nextNum = NextNum(num);private static int NextNum(int arg){ return arg + 1;}8. Introduce Local Extension (引入本地擴充)解釋:
如果我不想使用 Introduce Foreign Method, 我覺得它就本來應該實現某某功能, 如果被調用的類不是密封 (sealed) 的話, 可以自訂一個資料類型, 繼承這個類, 在自己定義的資料類型中實現我想要它實現的功能, 這就是 Introduce Local Extension.
本文連結: http://www.cnblogs.com/technology/archive/2011/05/11/2043307.html