当前位置: 移动技术网 > IT编程>开发语言>c# > C# 重构

C# 重构

2019年12月28日  | 移动技术网IT编程  | 我要评论

 

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

        }
    }

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

 

 

 重构后:

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

    }
}

 

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

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

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网