Reconstruction Techniques: handling generalization relationships [1]. Reconstruction Techniques: generalization relationships
Total returned directory
Directory of this section
- Pull Up Field (Field move Up)
- Pull Up Method (function move Up)
- Pull Up Constructor Body (Constructor ontology moving Up)
1 Pull Up Field (Field Moving Up) Summary
The two subclasses have the same field.Move this field to the base class.
Motivation
If each subclass is developed separately or combined during the refactoring process, you will often find that they are repetitive, especially fields that are easy to repeat. The only way to determine whether several fields are repeated is to observe how the function uses them. If they are used in a similar way, they can be summarized into the base class.
Example
The following code shows that both Salesman and Enginner sub-classes of Employee have the _ name field. Therefore, you can consider referring this field to the base class.
class Employee{}class Salesman : Employee{ private string _name;}class Enginner : Employee{ private string _name;}
The restructured code is as follows. The premise is that these subclasses have a base class or many similar fields and Methods. Otherwise, it is not advisable to create an abstract class for a field, therefore, this requires a specific trade-off.
class Employee{ protected string _name;}class Salesman : Employee{ }class Enginner : Employee{}
Summary
This refactoring mainly reduces duplication: First, it removes repeated data declarations; secondly, it allows you to move the behavior of this field from the subclass to the base class to remove repeated behavior.
2 Pull Up Method (function move Up) Summary
Some functions generate identical results in each subclass.Move the function to the base class.
Motivation
It is important to avoid repeated behaviors. Although the two repeated functions can also work well, repeating itself will only become a breeding ground for errors, and there is no value in it. At any time, as long as there are duplicates in the system, you are at risk of "modifying one but failing to modify the other.
When this item is used for refactoring: (1) If a function has the same body in each subclass, (2) if the subclass function overwrites the base class function, but still do the same work.
Example
"Customer" indicates "Customer". It has two sub-classes: RegularCustomer indicating "common Customer" and PreferredCustomer indicating "VIP.
public abstract class Customer{ protected DateTime _lastBillDate; public void AddBill(DateTime date, double amount) { }}class RegularCustomer : Customer{ void CreateBill(DateTime date) { double chargeAmount = ChargeFor(_lastBillDate, date); AddBill(date, chargeAmount); } public double ChargeFor(DateTime start, DateTime end) { return 0; }}class PreferredCustomer : Customer{ void CreateBill(DateTime date) { double chargeAmount = ChargeFor(_lastBillDate, date); AddBill(date, chargeAmount); } public double ChargeFor(DateTime start, DateTime end) { return 100; }}
Both subclasses have a CreateBill () function, and the code is exactly the same, but I cannot directly move this function to the base class, because the ChargeFor () function of each subclass is not the same. You must declare a ChargeFor () abstract function in the base class first:
public abstract class Customer{ protected DateTime _lastBillDate; protected void AddBill(DateTime date, double amount) { } protected void CreateBill(DateTime date) { double chargeAmount = ChargeFor(_lastBillDate, date); AddBill(date, chargeAmount); } public abstract double ChargeFor(DateTime start, DateTime end);}class RegularCustomer : Customer{ public override double ChargeFor(DateTime start, DateTime end) { return 0; }}class PreferredCustomer : Customer{ public override double ChargeFor(DateTime start, DateTime end) { return 100; }}
Summary
This refactoring should be used according to the actual situation. If not every subclass has this method, you can consider using interfaces or other methods.
3 Pull Up Constructor Body (Constructor ontology moving Up) Overview
You have some constructors in each subclass, and their ontology is almost identical.
Create a new constructor in the base class and call it in the subclass constructor.
Motivation
If you see that the functions in each subclass share the same behavior, the first thought should be to extract the common behavior into an independent function and then promote the function to the base class. For constructors, the common behavior of each other is often "Object Construction ". At this time, you need to provide a constructor in the base class, and then let the subclass call it.
Example
class Employee{ protected string _name; protected string _id;}class Manager:Employee{ private int _grade; public Manager(string name,string id,int grade) { _name = name; _id = id; _grade = grade; }}
The value of the Employee field should be set in the Employee constructor. Therefore, an Employee constructor is defined and declared as Protected, indicating that the subclass should call it:
class Employee{ protected string _name; protected string _id; protected Employee(string name, string id) { _name = name; _id = id; }}class Manager : Employee{ private int _grade; public Manager(string name, string id, int grade) : base(name, id) { _grade = grade; }}
Summary
This refactoring method is similar to the method for raising fields and improving fields. It is only to promote the "Object Construction" to the base class.
To Be Continued ......