重構 - 改善既有程式的設計 - Large Class
April 10, 2020這篇文章討論《重構 - 改善既有程式的設計》裡的3.3 - Large Class
圖片以及程式碼來源自重構 - 改善既有程式的設計
過大的類別
一個類別不應該太大 太大的類別很難維護
起因
大家習慣把新需求加到現有的類別裡 所以類別越變越大 味道越變越怪
解法
來聊聊常見的解法
Extract Class
你可以用Single Responsibility Principle簡單的判斷一個類別的責任是不是太多 是的話就拆分成兩個類別
我們有個Person
class Person{
public String getName() {
return _name;
}
public String getTelephoneNumber() {
return ("(" + _officeAreaCode + ") " + _officeNumber);
}
String getOfficeAreaCode() {
return _officeAreaCode;
}
void setOfficeAreaCode(String arg) {
_officeAreaCode = arg;
}
String getOfficeNumber() {
return _officeNumber;
}
void setOfficeNumber(String arg) {
_officeNumber = arg;
}
private String _name;
private String _officeAreaCode;
private String _officeNumber;
}
恩…這個Person
的責任好像有點太多 看起來要把電話號碼相關的資料分離出來
class TelephoneNumber {
String getAreaCode() {
return _areaCode;
}
void setAreaCode(String arg) {
_areaCode = arg;
}
private String _areaCode;
}
簡單 然後只要把TelephoneNumber丟進Person裡就搞定
class Person{
public String getName() {
return _name;
}
public String getTelephoneNumber(){
return _officeTelephone.getTelephoneNumber();
}
TelephoneNumber getOfficeTelephone() {
return _officeTelephone;
}
private String _name;
private TelephoneNumber _officeTelephone = new TelephoneNumber();
}
Extract Subclass
當你發現你這個類別的某些feature只被部分的instance使用 那就可以考慮一個SubClass
把所有物件都會用到的放在Parent Class 把少部分物件才會用到的放在Derived Class
Extract Subclass 跟 Extract Class 概念很接近 差別就差在你要選擇復合還是繼承
Extract Interface
很多個客戶都只用一個類別的某些方法們 或是兩個類別有某些方法相同 就可以把這某些方法給提煉出來
今天我要對 Employee 收費 我需要呼叫的是getRate()
跟hasSpecialSkill()
其他的我不在乎
double charge(Employee emp, int days) {
int base = emp.getRate() * days;
if (emp.hasSpecialSkill())
return base * 1.05;
else return base;
}
那就可以把這兩個函式分離出來
interface Billable {
public int getRate();
public boolean hasSpecialSkill();
}
變成這樣
double charge(Billable bil, int days) {
int base = bil.getRate() * days;
if (bil.hasSpecialSkill())
return base * 1.05;
else return base;
}
這樣之後即使charge()
要對Employee以外的類別收費 只要請那個類別實作Billable
就可以