Powerful Google developer tools for immediate impact! (2023-24 C)
Refactoring Chapter11
1. Refactoring: Improving the Design of
Existing Code
Chapter 11
Dealing with Generalization
Abner Huang
2013/10/11
2. Generalization
Moving methods around a hierarchy of
inheritance
Pull Up Field
Pull Up Method
Push Down Method
Push Down Field
Pull Up Constructor Body
……
4. Push down Field
If a field is used only by some subclasses, then move
the field to those subclasses.
5. Push down Field (cont.)
Declare the field in all subclasses.
Remove the field from the superclass.
Compile and test.
Remove the field from all subclasses that don’t
need it.
Compile and test.
6. Pull up Field
Two subclasses have the same field. Move the field to
the superclass.
7. Push Down Method
Behavior on a superclass is relevant only for some of its
subclasses. Move it to those subclasses
8. Declare a method in all subclasses and copy the body
into each subclass.
Remove method from superclass.
Compile and test.
Remove the method from each subclass that does not
need it.
Compile and test.
9. Pull up Method
You have methods with identical results on subclasses.
Move them to the superclass
10. If the method calls another method that is present on
both subclasses but not the superclass, declare an
abstract method on the superclass.
If the method uses a subclass field, use Pull Up Field or
Self Encapsulate Field and declare and use an abstract
getting method.
11. Pull up Constructor Body
You have constructors on subclasses with mostly
identical bodies. Create a superclass constructor; call
this from the subclass methods.
Use super() in JAVA
C++ has no super(); it use child_ctor(): parent_ctor() {};
12. class Employee...
protected String _name;
protected String _id;
boolean isPriviliged() {..}
void assignCar() {..}
class Manager...
private int _grade;
public Manager (String name, String id, int
grade) {
super (name, id);
_grade = grade;
if (isPriviliged()) assignCar();
//every subclass does this
}
13. Extract Subclass
A class has features that are used only in some
instances. Create a subclass for that subset of features
14. I’ll start with a job item class that determines prices for
items of work at a local garage. If we have the following
code
class JobItem ...
public JobItem (int unitPrice, int quantity, boolean
isLabor, Employee employee) {
_unitPrice = unitPrice;
_quantity = quantity;
_isLabor = isLabor;
_employee = employee;
}
public int getUnitPrice(){
return (_isLabor)? _employee.getRate():
_unitPrice;
}
15. We add the following class
class LaborItem ...
public LaborItem (int quantity, Employee employee) {
super (0, quantity, true);
_employee = employee;
}
16. get rid of the isLabor field.
class JobItem...
protected boolean isLabor() {
return false;
}
class LaborItem...
protected boolean isLabor() {
return true;
}
17. class JobItem...
public int getUnitPrice(){
return (isLabor()) ? _employee.getRate():
_unitPrice;
}
replace it with
class JobItem...
public int getUnitPrice(){return _unitPrice; }
class LaborItem...
public int getUnitPrice(){return _employee.getRate(); }
18. Extract Superclass
You have two classes with similar features. Create a
superclass and move the common features to the
superclass.
19. class Employee...
public Employee (String name, String id, int
annualCost) {
_name = name;
_id = id;
_annualCost = annualCost;
}
private String _name;
private int _annualCost;
private String _id;
. . .
//And their getters.
20. public class Department...
public Department (String name) {
_name = name;
}
public int getTotalAnnualCost(){
Enumeration e = getStaff();
int result = 0;
while (e.hasMoreElements()) {
Employee each = (Employee) e.nextElement();
result += each.getAnnualCost();
}
return result;
}
private String _name;
private Vector _staff = new Vector();
. . .
21. Use Pull Up Constructor Body to assign the name
class Party...
protected Party (String name) { _name = name; }
private String _name;
class Department...
public Department (String name) { super (name); }
class Employee...
public Employee (String name, String id, int
annualCost) {
super (name);
_id = id;
_annualCost = annualCost;
}
22. The methods Department.getTotalAnnualCost and
Employee.getAnnualCost, do carry out the same intention, so
they should have the same name.
cannot use Pull Up Method
Add abstract public int getAnnualCost() to superclass.
class Department...
public int getAnnualCost(){
Enumeration e = getStaff();
int result = 0;
while (e.hasMoreElements()) {
Party each = (Party) e.nextElement();
result += each.getAnnualCost();
}
return result;
}
23. Extract Interface
Several clients use the same subset of a class’s interface,
or two classes have part of their interfaces in common.
24. Collapse Hierarchy
A superclass and subclass are not very different. Merge
them together.
25. Form Template Method
You have two methods in subclasses that perform
similar steps in the same order, yet the steps are
different.
Class Customer {
public String statement() { … }
public String html_statement() { … }
…
}
26. 1. Template Method [GoF]:
Build a template for functions for the same tasks with
the same workflow
2. Pull up Method
27. class Customer...
public String statement() {
return new TextStatement().value(this);}
public String htmlStatement() {
return new HtmlStatement().value(this);}
class Statement...
abstract String headerString(Customer aCustomer);
abstract String eachRentalString (Rental aRental);
abstract String footerString (Customer aCustomer);
public String value(Customer aCustomer) {
out = headerString(aCustomer);
while (rentals.hasMoreElements()) {
out += eachRentalString(each);
}
out += footerString(aCustomer);
}
28. Replace Inheritance with Delegation
A subclass uses only part of a superclasses interface or
does not want to inherit data. Create a field for the
superclass, adjust methods to delegate to the
superclass, and remove the subclassing.
29. Replace Delegation with Inheritance
You’re using delegation and are often writing many
simple delegations for the entire interface. Make the
delegating class a subclass of the delegate.
30. A couple of caveats
Don’t use this technique, if you aren’t using all the
methods of the class to which you are delegating
beware of is that in which the delegate is shared by more
than one object and is mutable.