欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# 重构

程序员文章站 2022-06-04 09:48:22
一、Pull Up Field 提取字段 多个类中有相同的字段,可以提取到父类中。 重构前: public class Engineer { public string name { get; set; } } public class Salesman { public string name { ......

 

一、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)
        {

        }
    }

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

C# 重构

 

 

 重构后:

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

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

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

   

}

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

    }
}

C# 重构

 

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

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

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