這篇文章討論《重構 - 改善既有程式的設計》裡的3.3 - Large 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(); }
當你發現你這個類別的某些feature只被部分的instance使用 那就可以考慮一個SubClass
把所有物件都會用到的放在Parent Class 把少部分物件才會用到的放在Derived Class
Extract Subclass 跟概念很接近 差別就差在你要選擇復合還是繼承
很多個客戶都只用一個類別的某些方法們 或是兩個類別有某些方法相同 就可以把這 某些方法 給提煉出來
今天我要對 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
就可以