C# 重构

一、Pull Up Field 提取字段

多个类中有相同的字段,可以提取到父类中。

重构前:

   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
    {
         
    }

二、Pull_Up_Method 提取方法

多个类中有相同或相似的方法时,可以提取到父类

重构前:

    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为抽象方法。子类通过重写实现。

三、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方法实现不同,在父类中做成抽象方法。

四、Extract_Subclass 提炼子类

当一个类中出现根据类型调用不同的方法,或者一个类中有多个职责的时候,我们可以考虑提炼子类

重构前:

  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

比如这个打印类中,根据类型,调不同的打印方法。

 重构后:

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

五、Extract Superclass 提炼父类

几个类的字段,方法,构造函数等都有部分相同之处,可以提取到父类中。

重构前:

  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方法,获取费用。我们可以提取到父类中,修改成相同的名称。

重构后:

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

六、Form Template Method 模板方法

两个方法中的流程大致相同,我们可以提炼成模板方法。

重构前:

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

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

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

            return result;
        }

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

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

            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() + "
";
        }
        protected override string DetailString(string detailInfo)
        {
            return "Details is" + detailInfo + "
";
        }

        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>
";
        }

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

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

    }
}

 把不同的部分,用抽象函数代替。子类中去重写实现具体实现。

七、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);
        }
    }

八、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();
        }
    }

代码结构清晰简洁了不少。

原文地址:https://www.cnblogs.com/czly/p/12107169.html