C# 重構

 

1、Pull Up Field 提取字段

多個類中有相同的字段,能夠提取到父類中。json

重構前:

   public class Engineer
    {
        public string name { get; set; }
    }

    public class Salesman
    {
        public string name { get; set; }
    }

重構後:

    public class Employee
    {
        public string name { get; set; }
    }


    public class Engineer:Employee
    {
        
    }

    public class Salesman : Employee
    {
         
    }

 

2、Pull_Up_Method 提取方法

多個類中有相同或類似的方法時,能夠提取到父類api

重構前:

    class Preferred_Customer 
    {
        void CreateBill(DateTime date)
        {
            double chargeAmount = ChargeFor();
            AddBill(date, chargeAmount);
        }


        void AddBill(DateTime date, double amount)
        {
             
        }

        public  double ChargeFor()
        {
            return 1;
        }
    }
    class Regular_Customer
    {
        void CreateBill(DateTime date)
        {
            double chargeAmount = ChargeFor();
            AddBill(date, chargeAmount);
        }


        void AddBill(DateTime date, double amount)
        {

        }

        double ChargeFor()
        {
            return 2;
        }
    }

重構後:

 abstract class Customer
    {
        void CreateBill(DateTime date)
        {
            double chargeAmount = ChargeFor();
            AddBill(date, chargeAmount);
        }


        void AddBill(DateTime date, double amount)
        {

        }

        public abstract double ChargeFor();


    }

    class Preferred_Customer: Customer
    {
        public override  double ChargeFor()
        {
            return 1;
        }
    }

    class Regular_Customer:Customer
    {

        public override  double ChargeFor()
        {
            return 2;
        }
    }

子類中的ChargeFor方法實現不一樣,父類中的ChargeFor爲抽象方法。子類經過重寫實現。ide

 

3、Pull_Up_Constructor_Body 提取構造函數

多個類的構造函數代碼相似,能夠提取到父類中函數

重構前:

    class Manager 
    {
        string _name;
        int _id;

        public Manager(string name,int id)
        {
            _name = name;
            _id = id;

            Init();
        }

        void Init()
        {
            object obj1 = new object();
        }
    }

    class Manager1
    {
        string _name;
        int _id;
        int _grade;
        public Manager1(string name,int id,int grade)
        {
            _name = name;
            _id = id;
            _grade = grade;

            Init();
        }

        void Init()
        {
            object obj2 = new object();
            _grade = 2;
        }
    }

重構後:

 abstract class Employee
    {
        protected string _name;
        protected int _id;

        public Employee(string name, int id)
        {
            _name = name;
            _id = id;
            Init();
        }

        protected abstract void Init();
    }

    class Manager:Employee
    {

        public Manager(string name, int id):base(name,id)
        {

        }

        protected override void Init()
        {
            object obj1 = new object();
        }
    }

    class Manager1 : Employee
    {
        int _grade;
        public Manager1(string name, int id, int grade) : base(name, id)
        {
            _grade = grade;
        }

        protected override void Init()
        {
            object obj2 = new object();
            _grade = 2;
        }
    }

子類中的構造函數中調用的Init方法實現不一樣,在父類中作成抽象方法。spa

4、Extract_Subclass 提煉子類

當一個類中出現根據類型調用不一樣的方法,或者一個類中有多個職責的時候,咱們能夠考慮提煉子類3d

重構前:

  class PrintClass
    {
        string _path;
        string _jsonData;
        string _sourceBillFlag;
        List<int> _sourceBillId;
        int _lableType;

        public PrintClass(string path, string jsonData, string sourceBillFlag, List<int> sourceBillId, int lableType)
        {
            _path = path;
            _jsonData = jsonData;
            _sourceBillFlag = sourceBillFlag;
            _sourceBillId = sourceBillId;
            _lableType = lableType;
        }

       public void Print()
        {
            switch(_lableType)
            {
                case 1:
                    PrintBartender(_path,_jsonData);
                    break;
                case 2:
                    PrintCodeSoft(_path, _jsonData);
                    break;
                case 3:
                    PrintCloud(_sourceBillFlag,_sourceBillId);
                    break;
            }
        }

        void PrintBartender(string path, string jsonData)
        {

        }

        void PrintCodeSoft(string path, string jsonDat)
        {

        }

        void PrintCloud(string sourceBillFlag, List<int> sourceBillId)
        {

        }
    }
View Code

好比這個打印類中,根據類型,調不一樣的打印方法。code

 

 

 重構後:

namespace Extract_Subclass
{
    class PrintBase
    {
        string _path;
        string _jsonData;
        public PrintBase(string path, string jsonData)
        {
            _path = path;
            _jsonData = jsonData;
        }

       public virtual void Print( )
        {

        }
    }

    class BartenderPrint : PrintBase
    {
        public BartenderPrint(string path, string jsonData):base(path,jsonData)
        {
            
        }

        public override void Print()
        {
            //call bartender api
        }
    }

    class CodeSoftPrint : PrintBase
    {
        public CodeSoftPrint(string path, string jsonData) : base(path, jsonData)
        {

        }

        public override void Print()
        {
            //call CodeSoft api
        }
    }

    class CloudPrint:PrintBase
    {
        string _sourceBillFlag;
        List<int> _sourceBillId;
        public CloudPrint(string sourceBillFlag, List<int> sourceBillId) :base("","")
        {
            _sourceBillFlag = sourceBillFlag;
            _sourceBillId = sourceBillId;
        }

        public override void Print()
        {
           //Cloud print
        }
    }
}
View Code

5、Extract Superclass 提煉父類

幾個類的字段,方法,構造函數等都有部分相同之處,能夠提取到父類中。orm

重構前:

  class Department
    {
        string _name;

        public Department(string name)
        {
            _name = name;
             
        }

        public string GetName()
        {
            return _name;
        }

        public int GetTotalaAnnualCost()
        {
            int result = 0;

            GetStaff().ForEach(p=>
            {
                result += p.GetAnnualCost();
            });

            return result;
        }

        private List<Employee> GetStaff()
        {
            return default(List<Employee>);
        }
    }
View Code
 class Employee
    {
        string _name;
        string _id;
        int _annualCost;

        public Employee(string name,string id,int annualCost)
        {
            _name = name;
            _id = id;
            _annualCost = annualCost;
        }

        public string GetName()
        {
            return _name;
        }

        public int GetAnnualCost()
        {
            return _annualCost;
        }
    }
View Code

Department類中有個GetTotalaAnnualCost方法,獲取總費用,Employee中有個GetAnnualCost方法,獲取費用。咱們能夠提取到父類中,修改爲相同的名稱。blog

重構後:

namespace RefactoringDome.Extract_Superclass
{
   abstract class Part
    {
        string _name;

        public Part(string name)
        {
            _name = name;

        }

        public string GetName()
        {
            return _name;
        }

        public abstract int GetAnnualCost();
         
    }
}

namespace RefactoringDome.Extract_Superclass.Dome
{
    class Employee : Part
    {
        string _id;
        int _annualCost;

        public Employee(string name, string id, int annualCost) : base(name)
        {
            _id = id;
            _annualCost = annualCost;
        }

        public override int GetAnnualCost()
        {
            return _annualCost;
        }
    }

    class Department:Part
    {
    
        public Department(string name):base(name)
        {

        }

        public override int GetAnnualCost()
        {
            int result = 0;

            GetStaff().ForEach(p =>
            {
                result += p.GetAnnualCost();
            });

            return result;
        }

        private List<Employee> GetStaff()
        {
            return default(List<Employee>);
        }
    }

   

}
View Code

6、Form Template Method 模板方法

兩個方法中的流程大體相同,咱們能夠提煉成模板方法。繼承

重構前:

   class Customer
    {
        public string Statement()
        {
            List<string> details = GetDetails();

            string result = "Rental Record for" + GetName() + "\n";
            details.ForEach(p=>
            {
                result += "Details is" + p + "\n";
            });

            result += "Total Charge:"+GetTotalCharge();

            return result;
        }

        public string HtmlStatement()
        {
            List<string> details = GetDetails();

            string result = "<h1>Rental Record for<EM>" + GetName() + "</EM></h1>\n";
            details.ForEach(p =>
            {
                result += "<p>Details is<EM>" + p + "</EM></p>\n";
            });

            result += "<p>Total Charge:<EM>" + GetTotalCharge()+"</EM></p>";

            return result;
        }

        public List<string> GetDetails()
        {
            return default(List<string>);
        }

        public string GetName()
        {
            return "";
        }

        public decimal GetTotalCharge()
        {
            return 0;
        }

        
    }

Customer類中有兩個打印小票的方法,一個是winform調的,一個是Html調的。方法中代碼結構同樣,只是部分顯示字符串不一樣。

這種很符合提取成模板函數。

重構後:

namespace RefactoringDome.Form_Template_Method
{
    abstract class Statement
    {
        public string Value(Customer customer)
        {
            List<string> details = customer.GetDetails();

            string result = HeaderString(customer);
            details.ForEach(p =>
            {
                result += DetailString(p);
            });

            result += FooterString(customer);

            return result;
        }


        protected abstract string HeaderString(Customer customer);
        protected abstract string DetailString(string detailInfo);
        protected abstract string FooterString(Customer customer);

    }

    class TextStatement : Statement
    {

        protected override string HeaderString(Customer customer)
        {
            return "Rental Record for" + customer.GetName() + "\n";
        }
        protected override string DetailString(string detailInfo)
        {
            return "Details is" + detailInfo + "\n";
        }

        protected override string FooterString(Customer customer)
        {
            return "Total Charge:" + customer.GetTotalCharge();
        }
    }

    class HtmlStatement : Statement
    {

        protected override string HeaderString(Customer customer)
        {
            return "<h1>Rental Record for<EM>" + customer.GetName() + "</EM></h1>\n";
        }

        protected override string DetailString(string detailInfo)
        {
            return "<p>Details is<EM>" + detailInfo + "</EM></p>\n";
        }

        protected override string FooterString(Customer customer)
        {
            return "<p>Total Charge:<EM>" + customer.GetTotalCharge() + "</EM></p>";
        }

    }
}

 

 把不一樣的部分,用抽象函數代替。子類中去重寫實現具體實現。

7、Replace Inheritance with Delegation 繼承替換爲委託

子類只用了父類一小部分方法。這種狀況能夠考慮將繼承替換爲委託。

重構前:

    class List
    {
        public object FirstElement()
        {
            return default(object);
        }

        public void Insert(object element)
        {

        }

        public void Remove(object element)
        {
            
        }


        public int FindIndex(object obj)
        {
            return 0;
        }

        public void Sort()
        {

        }
    }

    class Queue: List
    {
        public void Push(object element)
        {
            Insert(element);
        }

        public void Pop()
        {
            object obj = FirstElement();
            Remove(obj);
        }
    }

Queue類繼承了List類,使用了List類的Insert、Remove、FirstElement方法。可是List類中還有Sort、FindIndex方法在子類中沒有用到。這樣父類傳達給調用端的信息並非你想要體現的。這種狀況咱們應該使用List的委託。

重構後:

 class Queue  
    {
        List _list = new List();
        public void Push(object element)
        {
            _list.Insert(element);
        }

        public void Pop()
        {
            object obj = _list.FirstElement();
            _list.Remove(obj);
        }
    }

8、Replace Delegation with inheritance 委託替換爲繼承

一個類中,引用了另外一個類的實例,可是當前類中的方法,委託類裏都有,這種狀況應該用繼承替換委託。

重構前:

 class Employee
    {
        Person _person = new Person();

        public string GetName()
        {
           return  _person.GetName();
        }

        public void SetName(string name)
        {
             _person.SetName(name);
        }

        public new string ToString()
        {
            return "my name is:"+_person.GetLastName();
        }
    }

    class Person
    {
        string _name;
        
        public string GetName()
        {
            return _name;
        }

        public void SetName(string name)
        {
            _name = name;
        }

        public string GetLastName()
        {
            return _name.Substring(1);
        }
    }

 

重構後:

 class Employee:Person
    {
        public new string ToString()
        {
            return "my name is:" + GetLastName();
        }
    }

代碼結構清晰簡潔了很多。

相關文章
相關標籤/搜索