一、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 提炼子类
当一个类中出现根据类型调用不同的方法,或者一个类中有多个职责的时候,我们可以考虑提炼子类
重构前:
View Code
比如这个打印类中,根据类型,调不同的打印方法。
重构后:
View Code
五、Extract Superclass 提炼父类
几个类的字段,方法,构造函数等都有部分相同之处,可以提取到父类中。
重构前:
View Code
View Code
Department类中有个GetTotalaAnnualCost方法,获取总费用,Employee中有个GetAnnualCost方法,获取费用。我们可以提取到父类中,修改成相同的名称。
重构后:
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 = "<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方法c#教程。但是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();
}
}
代码结构python基础教程清晰简洁了不少。