最近在讀《重構(gòu)》這本書,試著把書中對(duì)我啟發(fā)較大的一些點(diǎn)記錄下來(lái),以便回顧學(xué)習(xí)昔搂。
一、replace temp with query(以查詢?nèi)〈R時(shí)變量)
在寫程序的過(guò)程中输拇,難免會(huì)在函數(shù)中定義一些臨時(shí)變量摘符,有些時(shí)候是無(wú)法避免的。但因?yàn)榕R時(shí)變量可能使用起來(lái)簡(jiǎn)單策吠、快捷议慰,因而有時(shí)會(huì)出現(xiàn)不恰當(dāng)?shù)氖褂谩R驗(yàn)橛行┡R時(shí)變量在定義之后只進(jìn)行了一次賦值奴曙,那么這種臨時(shí)變量是否有存在的價(jià)值就值得考慮别凹。把臨時(shí)相關(guān)的賦值操作抽象為一個(gè)函數(shù),以一個(gè)恰當(dāng)?shù)暮瘮?shù)名命名這個(gè)函數(shù)洽糟,那么便可將相應(yīng)的計(jì)算封裝起來(lái)炉菲,這樣計(jì)的算規(guī)則封裝在一個(gè)函數(shù)中堕战,可以將變化隔離獨(dú)立出來(lái),便于修改拍霜。
以書中的一段代碼為例:
double getPrice(){
int basePrice = _quantity * _itemPrice;
double discountFactor;
if(basePrice > 1000) {
discountFactor = 0.95;
} else {
discountFactor = 0.98;
}
return baseprice * discountFactor;
}
重構(gòu)后的代碼為:
double getPrice(){
return baseprice() * discountFactor();
}
int basePrice() {
return _quantity * _itemPrice;
}
double discountFactor() {
if(basePrice() > 1000) {
return 0.95;
} else {
return 0.98;
}
}
個(gè)人認(rèn)為這樣做的好處是basePrice和discountFactor的計(jì)算都隔離出來(lái)嘱丢,如果發(fā)生變化容易修改。此外祠饺,discountFactor()函數(shù)的1000,0.95等數(shù)字的可以通過(guò)常量的方式定義越驻,更加合理一點(diǎn)。
二道偷、replace method with method object(以函數(shù)對(duì)象取代函數(shù))
有時(shí)缀旁,可能會(huì)出現(xiàn)某個(gè)函數(shù)特別復(fù)雜,里面有大量的臨時(shí)變量以及復(fù)雜的運(yùn)算勺鸦,那么我們可以采用“以函數(shù)對(duì)象取代函數(shù)”的方法來(lái)對(duì)這個(gè)復(fù)雜的函數(shù)內(nèi)容進(jìn)行重構(gòu)并巍。
做法為將復(fù)雜的函數(shù)中使用到的臨時(shí)變量作為函數(shù)對(duì)象(MethodObject)的成員變量,原先函數(shù)中復(fù)雜的計(jì)算封裝到函數(shù)對(duì)象的某一個(gè)方法中(如compute())换途。
這樣即可以在原先復(fù)雜的函數(shù)中以new MethodObject(...).compute();取代原先的代碼懊渡。這樣的好處在于這段復(fù)雜的代碼方便復(fù)用、重構(gòu)以及變更军拟。
三剃执、Hide Delegate(隱藏委托關(guān)系)
- 首先是隱藏“委托關(guān)系”
有時(shí)客戶端需要先通過(guò)服務(wù)對(duì)象A的方法得到另一個(gè)對(duì)象B,然后再調(diào)用B的函數(shù)b懈息,這會(huì)產(chǎn)生一個(gè)“級(jí)聯(lián)調(diào)用”肾档。
有時(shí)我們需要隱藏這種“關(guān)系”,我們可以在在服務(wù)對(duì)象A上放置一個(gè)簡(jiǎn)單的“委托函數(shù)”a漓拾,在函數(shù)a的內(nèi)部調(diào)用B的函數(shù)b。
這樣的話客戶端只需要調(diào)用A對(duì)象的a函數(shù)即可戒祠。
《重構(gòu)》書中給出的例子如下:
class Person {
private Department department;
public Department getDepartment() {
return this.department;
}
public void setDepartment(Department department) {
this.department = department;
}
}
class Department {
private String code;
private Person manager;
public Department(Person manager) {
this.manager = manager;
}
public Person getPerson() {
return this.manager;
}
}
- 調(diào)用場(chǎng)景及問(wèn)題如下如下:
要獲取某部門的經(jīng)理:manager = john.getDepartment().getManager();
這樣的調(diào)用會(huì)暴露內(nèi)部實(shí)現(xiàn)骇两,并且調(diào)用端會(huì)和Department類產(chǎn)生耦合。
- 解決辦法:
在Person類中添加一個(gè)委托方法:
public Person getManager() {
return department.getManager();
}
manager = john.getManager();
這樣調(diào)用端就不需要知道Department類的信息姜盈,Department類發(fā)生變化時(shí)只需要通知Person類即可低千,易于維護(hù)。
- 額外說(shuō)明:
當(dāng)服務(wù)端的委托函數(shù)過(guò)多時(shí)馏颂,可能之前的重構(gòu)方案出現(xiàn)問(wèn)題示血,需要采用新的重構(gòu)方案。
如讓客戶端依賴受委托的對(duì)象救拉。
當(dāng)然难审,進(jìn)行重構(gòu)時(shí)還應(yīng)該具體情況具體分析。
持續(xù)更新
如有不正確的地方亿絮,歡迎指出告喊!謝謝大家麸拄!