改善代碼設計 —— 最佳化物件之間的特性(Moving Features Between Objects)

來源:互聯網
上載者:User
文章目錄
  • 解釋:
  • 衝動前:
  • 衝動後:
  • 解釋:
  • 衝動前:
  • 衝動後:
  • 解釋:
  • 衝動前:
  • 衝動後:
  • 解釋:
  • 解釋:
  • 衝動前:
  • 衝動後:
  • 解釋:
  • 解釋:
  • 衝動前:
  • 衝動後:
  • 解釋:
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 ClassExtract Class 正好相反. 當一個物件沒有做它應該做的事情, 還專門使用了另一個物件來協助它完成這個職責, 這時可以考慮使用 Inline Class.

      如上面所示的例子, 如果我覺得 Employee 這個物件本身就應該實現 Salary 的計算工作, 而不是專門寫一個 Salary 的計算物件來協助它計算, 可以使用 Inline ClassSalary 內聯到 Employee 中去, 也就是"衝動後"的代碼重構成"衝動前"代碼的樣子.

5. Hide Delegate (隱藏委託關係)解釋:

      試想這麼一個情況: 有一個 Employee 類, 這個類中含有一個部門 (Department) 屬性, 並且 Department 是一種類. 如果我想知道某職工所在部門的經理人是誰的時候, 我需要通過 xxEmployee.Department.Manger 來訪問. 但這樣做有個缺點是對於其它代碼,  Departmentpublic 的, 其它代碼能夠訪問到 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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.