一、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 GetStaff() { return default(List); } }
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 GetStaff() { return default(List); } } }
View Code
六、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 = "Rental Record for" + GetName() + "\n"; details.ForEach(p => { result += "Details is" + p + "\n"; }); result += "Total Charge:" + GetTotalCharge()+""; 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 "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() + ""; } } }
把不同的部分,用抽象函数代替。子类中去重写实现具体实现。
七、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(); } }
代码结构清晰简洁了不少。