现在进入面向对象的世界。
说两个让我印象深刻的重构:Replace Constructor With Factory Method和Replace Conditional With Polymorphism。
ReplaceConstructor With Factory Method常常用在根据类型码创建对象的地方。有3种情况:根据整数创建对象,根据字符串创建对象,用明确的函数创建对象。
有的时候一个类会有很多构造函数,每个构造函数之间只有细微的区别,此时我们要用能够说明意图的返回对象实例的Creation Method替换构造函数。
比如:
Loan::Loan(commitment, riskRating, maturity)
Loan::Loan(commitment, riskRating, maturity,expiry)
Loan::Loan(capitalStrategy, commitment,riskRating, maturity, expiry)
Loan::Loan(capitalStrategy, commitment, outstanding,riskRating, maturity)
对于这么多构造函数,很难决定在开发期间调用哪一个,我们可以选出一个构造函数作为全包含构造函数(catch-all constructor):
Loan::Loan(capitalStrategy, commitment, outstanding,riskRating, maturity)
然后创建一些静态函数,让它们相应调用全包含构造函数:
Loan::CreateTermLoan(commitment, riskRating, maturity)
Loan::CreateRevolver(commitment, riskRating, maturity, expiry)
Loan::CreateRCTL(capitalStrategy, commitment, riskRating,maturity, expiry)
再进一步,如果有太多的Creation Method,维护起来也不方便,此时我们可以考虑参数化Creation Method。
如果你觉得这么多Creation Method分散了类的主要职责,那么应该将Creation Method重构为一个Factory。
ReplaceConditional With Polymorphism用于简化条件表达式。
比如在一个类里面,有如下条件表达式:
Class Emplyee …
IntpayAmount() {
Switch(_type) {
case ENGINEER:
return _monthlySalary;
case SALESMAN:
return _monthlySalary +_commission;
case MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException(“IncorrectEmployee”);
}
}
}
先把类型码封装起来:
Class Emplyee …
void setType(int);
int getType();
IntpayAmount() {
Switch(getType()) {
case ENGINEER:
return _monthlySalary;
case SALESMAN:
return _monthlySalary +_commission;
case MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException(“IncorrectEmployee”);
}
}
}
然后把封装起来的类型码变成类:
abstract class EmployeeType {
abstract intgetTypeCode();
}
class Engineer extends EmployeeType {
intgetTypeCode() {
returnENGINEER;
}
}
class Manager extends EmployeeType {
intgetTypeCode() {
return MANAGER;
}
}
class Salesman extends EmployeeType {
intgetTypeCode() {
return SALESMAN;
}
}
Class Employee …
void setType(int arg) {
// Replace Constructor With Factory Method
_type = EmployeeType.newType(arg);
}
int getType() {
return _type.getTypeCode();
}
IntpayAmount() {
Switch(getType()) {
case EmployeeType.ENGINEER:
return _monthlySalary;
case EmployeeType.SALESMAN:
return _monthlySalary +_commission;
case EmployeeType.MANAGER:
return _monthlySalary + _bonus;
default:
throw new RuntimeException(“IncorrectEmployee”);
}
}
}
你可以把payAmount移动到EmployeeType里面了:
Class Employee …
IntpayAmount() {
return _type.payAmount (this);
}
}
Class EmployeeType …
IntpayAmount() {
Switch(getTypeCode()) {
case ENGINEER:
return emp.getMonthlySalary();
case SALESMAN:
return emp.getMonthlySalary() +emp.getCommission();
case MANAGER:
return emp.getMonthlySalary() +emp.getBonus();
default:
throw new RuntimeException(“IncorrectEmployee”);
}
}
}
最后我们把payAmount下移到这个继承体系中去:
abstract class EmployeeType {
abstract intpayAmount ();
}
class Engineer extends EmployeeType {
int payAmount() {
return emp.getMonthlySalary();
}
}
class Manager extends EmployeeType {
int payAmount() {
return emp.getMonthlySalary()+ emp.getBonus();
}
}
class Salesman extends EmployeeType {
int payAmount() {
return emp.getMonthlySalary()+ emp.getCommission();
}
}
这样switch语句就被替换为了多态,准确的说还有一处有switch语句,EmployeeType::newType,这个是无法避免的。