日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《重构:改善既有代码的设计》-学习笔记一(+实战解析)

發(fā)布時間:2025/3/15 编程问答 14 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《重构:改善既有代码的设计》-学习笔记一(+实战解析) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我不是個偉大的程序員;我只是個有著一些優(yōu)秀習慣的好程序員而己

本人比較直接,不說虛的,直接上干貨。

目錄

????Duplicated Code(重復的代碼)

????Long Method(過長函數(shù))

???? Long Parameter List(過長參數(shù)列)

????Large Class(過大類)

提前總結就是四招:

??? 一、重復的代碼提煉成函數(shù)

??? 二、把過長的函數(shù)變小

??? 三、參數(shù)列太長或變化太頻繁,參數(shù)對象化

??? 四、大招:類的代碼行數(shù)太多,要考慮提煉子類。

?

?第一招 重復的代碼提煉成函數(shù)

??? 第一種情況是:同一個class內的兩個函數(shù)含有相同表達式(expression)。

void printOwing(String _name) {Enumeration e =_orders.elements();double outstanding = 0.0;// print bannerSystem.out.println ("**************************");System.out.println ("***** Customer Owes ******");System.out.println ("**************************");// calculate outstandingwhile (e.hasMoreElements()) {Order each = (Order) e.nextElement();outstanding += each.getAmount();}//print detailsSystem.out.println ("name:" + _name);System.out.println ("amount" + outstanding);}

?

實際上這三部分都可以提煉。

優(yōu)化后的結果

void printOwing(String _name) {printBanner();double outstanding = getOutstanding();printDetails(_name,outstanding); }void printBanner() {// print bannerSystem.out.println ("**************************");System.out.println ("***** Customer Owes ******");System.out.println ("**************************");} void printDetails (String _name,double outstanding) {System.out.println ("name:" + _name);System.out.println ("amount" + outstanding); }double getOutstanding() {Enumeration e = _orders.elements();double result = 0.0;while (e.hasMoreElements()) {Order each = (Order) e.nextElement();result = each.getAmount();}return result;}

第二種情況:兩個subclasses有相同的表達式,或者是相似的表達式

??? 優(yōu)化的方法是:抽取相同的表達式(屬性和方法),放在父類里,兩個子類再去繼承。

********************************************************************************** ??????????

如果是相似的表達式,好抽出共性的,則用模板函數(shù)設計模式來處理。

這里用到了JAVA的兩個特性,繼承和多態(tài)。

優(yōu)化的思路1

1、在各個subclass 中分解目標函數(shù),把有差異的部分變成入參,封裝成一個模板函數(shù)。

2、把模板函數(shù)放到父類中。

3、子類根據需要輸入不同的入參,得到需要的結果。

*********************************************************************************

如果是相似的表達式,差異的地方不好抽共性,則用模板函數(shù)設計模式來處理。

這里用到了JAVA的兩個特性,繼承和覆寫(overrides)。

優(yōu)化的思路2

1、在各個subclass 中分解目標函數(shù),使分解后的各個函數(shù)要不完全相同,要不完全不同。

2、父類有一個主函數(shù)包含完全相同的函數(shù)和完全不同的函數(shù):相同的函數(shù),抽到父類中,不相同的函數(shù)在父類中定義一個函數(shù)。

3、子類繼承父類,然后覆寫完全不同的函數(shù),再調用主函數(shù)可得到期望的結果。

第二招 把過長的函數(shù)變小

百分之九十九的場合里,要把函數(shù)變小,只需使用Extract Method(第一招)。找到函數(shù)中適合集在一起的部分,將它們提煉出來形成一個新函數(shù)。

如果函數(shù)內有大量的參數(shù)和臨時變量,它們會對你的函數(shù)提煉形成阻礙。這時就要用Replace Temp with Query來消除這些臨時變量

Replace Temp with Query(以查詢取代臨時變量)

?優(yōu)化思路

1、找出只被賦值一次的臨時變量。

2、將該臨時變量聲明為final

3、編譯:這可確保該臨時變量的確只被賦值一次。

4、將臨時變量等號右側部分提煉到一個獨立函數(shù)中;

5、首先將函數(shù)聲明為private。日后你可能會發(fā)現(xiàn)有更多class需要使用 它,彼時你可再放松對它的保護。

6、編譯,測試:確保提煉出來的函數(shù)無任何連帶影響(副作用),結果不變;

7、把臨時變量全替換成獨立出來的函數(shù);

以上,over!

例子:未優(yōu)化代碼

double getPrice() {int basePrice = _quantity * _itemPrice;double discountFactor;if (basePrice > 1000) discountFactor = 0.95;else discountFactor = 0.98;return basePrice * discountFactor;}

開始優(yōu)化 1~3步驟

double getPrice() {final int basePrice = _quantity * _itemPrice;final double discountFactor;if (basePrice > 1000) discountFactor = 0.95;else discountFactor = 0.98;return basePrice * discountFactor;}

4~6步驟

double getPrice() {final int basePrice = basePrice();final double discountFactor;if (basePrice > 1000) discountFactor = 0.95;else discountFactor = 0.98;return basePrice * discountFactor;}private int basePrice() {return _quantity * _itemPrice;}

7步驟

double getPrice() {final double discountFactor;if (basePrice() > 1000) discountFactor = 0.95;else discountFactor = 0.98;return basePrice() * discountFactor;} private int basePrice() {return _quantity * _itemPrice;}

搞定basePrice之后,再以類似辦法提煉出一個discountFactor():

double getPrice() {final double discountFactor = discountFactor();return basePrice() * discountFactor;}private double discountFactor() {if (basePrice() > 1000) return 0.95;else return 0.98;}

最后的效果

double getPrice() {return basePrice() * discountFactor();}private double discountFactor() {if (basePrice() > 1000) return 0.95;else return 0.98;}private int basePrice() {return _quantity * _itemPrice;}

通過以上的優(yōu)化,一個大函數(shù),已經變成了多個小函數(shù),重點是代碼的可讀性提高了,順帶的代碼量變少。

第三招 參數(shù)對象化

當你看到一個函數(shù)的入參有四,五個,甚至更多時,且好幾個函數(shù)都使用這組入參,這時就要用參數(shù)對象化來優(yōu)化代碼。這些函數(shù)可能隸屬同一個class,也可能隸屬不同的classes 。這樣一組參數(shù)就是所謂的Date Clump (數(shù)據泥團)」。這時用一個對象封裝這些參數(shù),再用對象取代它們。

優(yōu)化思路

1、入參有四,五個,甚至更多時,就要著手優(yōu)化;

2、用一個新的class封裝入參,并把這些參數(shù)設置為private嚴格保護起來,寫這些參數(shù)的get方法和set方法。

3、原函數(shù)的入參變成這個新的class對象,函數(shù)里的參數(shù)用class對象對應的屬性替換。

4、編譯測試;

5、將原先的參數(shù)全部去除之后,觀察有無適當函數(shù)可以運用Move Method 搬移到參數(shù)對象之中。

例子:未優(yōu)化的代碼

@Autowiredprivate AddressService addressService;public List inquireAddressListAccount( Integer pageNum ,Integer pageSize,String addressName,String mobile,String zipCode,String consignee){return addressService.inquireAddressList(pageNum,pageSize,addressName,mobile,zipCode,consignee);}

?

優(yōu)化

@Autowiredprivate AddressService addressService;public List inquireAddressListAccount( Integer pageNum ,Integer pageSize,InquireAddressListInput output){return addressService.inquireAddressList(pageNum,pageSize,output);}public class InquireAddressListInput(){private String addressName;private String mobile;private String zipCode;private String consignee;public String getConsignee() {return consignee;}public void setConsignee(String consignee) {this.consignee = consignee;}public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}public String getZipCode() {return zipCode;}public void setZipCode(String zipCode) {this.zipCode = zipCode;}public String getAddressName() {return addressName;}public void setAddressName(String addressName) {this.addressName = addressName;}}

第四招 大招-提煉類和提煉子類

如果想利用單一class做太多事情,其內往往就會出現(xiàn)太多instance變量。一旦如此,Duplicated Code也就接踵而至了。

Extract Class 是Extract Subclass 之外的另一種選擇,兩者之間的抉擇其實就是委托(delegation)和繼承(inheritance)之間的抉擇。

情況一:某個class做了應該由兩個classes做的事。(Extract Class)

優(yōu)化思路1

1、明確每個class所負的責任,該做什么事情;

2、建立一個新class,用以表現(xiàn)從舊class中分離出來的責任;

3、建立「從舊class訪問新class」的連接關系;

4、每次搬移后,編譯、測試。

5、決定是否讓新的class曝光。

例子:未優(yōu)化的代碼

class Person{private String _name;private String _officeAreaCode;private String _officeNumber;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;}}

優(yōu)化1~2步驟

可以將「與電話號碼相關」的行為分離到一個獨立class中

class TelephoneNumber{private String _number;private String _areaCode;public String getTelephoneNumber() {return ("(" + _areaCode + ") " + _number);}String getAreaCode() {return _areaCode;}void setAreaCode(String arg) {_areaCode = arg;}String getNumber() {return _number;}void setNumber(String arg) {_number = arg;}}

?

優(yōu)化3步驟

class Person...private String _name;private TelephoneNumber _officeTelephone = new TelephoneNumber();public String getName() {return _name;}public String getTelephoneNumber(){return _officeTelephone.getTelephoneNumber();}TelephoneNumber getOfficeTelephone() {return _officeTelephone;}

情況二:class 中的某些特性(features)只被某些(而非全部)實體(instances)用到。Extract Subclass(提煉子類)

優(yōu)化思路2

1、為source class 定義一個新的subclass

2、為這個新的subclass 提供構造函數(shù)。

????簡單的作法是:讓subclass 構造函數(shù)接受與superclass 構造函數(shù)相同的參數(shù),并通過super 調用superclass 構造函數(shù);

3、找出調用superclass 構造函數(shù)的所有地點。如果它們需要的是新建的subclass , 令它們改而調用新構造函數(shù)。

????如果subclass 構造函數(shù)需要的參數(shù)和superclass 構造函數(shù)的參數(shù)不同,可以使用Rename Method 修改其參數(shù)列。如果subclass 構造函數(shù)不需要superclass 構造函數(shù)的某些參數(shù),可以使用Rename Method 將它們去除。

????如果不再需要直接實體化(具現(xiàn)化,instantiated)superclass ,就將它聲明為抽象類。

4、逐一使用Push Down Method 和 Push Down Field 將source class 的特性移到subclass 去。

5、每次下移之后,編譯并測試。

例子:未優(yōu)化代碼

--用來決定當?shù)匦捃噺S的工作報價:

class JobItem ...public JobItem (int unitPrice, int quantity, boolean isLabor, Employee employee) {_unitPrice = unitPrice;_quantity = quantity;_isLabor = isLabor;_employee = employee;}public int getTotalPrice() {return getUnitPrice() * _quantity;}public int getUnitPrice(){return (_isLabor) ?_employee.getRate():_unitPrice;}public int getQuantity(){return _quantity;}public Employee getEmployee() {return _employee;}private int _unitPrice;private int _quantity;private Employee _employee;private boolean _isLabor;class Employee...public Employee (int rate) {_rate = rate;}public int getRate() {return _rate;}private int _rate;

?

優(yōu)化1步驟

class LaborItem extends JobItem {}

優(yōu)化2步驟

class LaborItem extends JobItem {public LaborItem (int unitPrice, int quantity, boolean isLabor, Employee employee) {super (unitPrice, quantity, isLabor, employee);}}

這就足以讓新的subclass 通過編譯了。但是這個構造函數(shù)會造成混淆:某些參數(shù)是LaborItem 所需要的,另一些不是。稍后我再來解決這個問題。

優(yōu)化3步驟

清理構造函數(shù)參數(shù)列

class JobItem...protected JobItem (int unitPrice, int quantity, boolean isLabor, Employee employee) {_unitPrice = unitPrice;_quantity = quantity;_isLabor = isLabor;_employee = employee;}public JobItem (int unitPrice, int quantity) {this (unitPrice, quantity, false, null)}

?

外部調用應該使用新構造函數(shù):

? ? ? ?JobItem j2 = new JobItem (10, 15);

測試通過后,再使用Rename Method 修改subclass 構造函數(shù):

class LaborItempublic LaborItem (int quantity, Employee employee) {super (0, quantity, true, employee);}

可以將JobItem 的特性向下搬移。先從函數(shù)幵始,我先運用 Push Down Method 對付getEmployee() 函數(shù):

?

class LaborItem extends JobItem {public LaborItem (int unitPrice, int quantity, boolean isLabor, Employee employee) {super (unitPrice, quantity, isLabor, employee);}public LaborItem (int quantity, Employee employee) {super (0, quantity, true, employee);}public Employee getEmployee() {return _employee;}}//因為_employee 值域也將在稍后被下移到LaborItem ,所以我現(xiàn)在先將它聲明為protected。 class JobItem...protected Employee _employee;

將_employee 值域聲明protected 之后,我可以再次清理構造函數(shù),讓_employee 只在「即將去達的subclass 中」被初始化:

class JobItem...protected Employee _employee;protected JobItem (int unitPrice, int quantity, boolean isLabor) {_unitPrice = unitPrice;_quantity = quantity;_isLabor = isLabor;}class LaborItem ...public LaborItem (int quantity, Employee employee) {super (0, quantity, true);_employee = employee;}

下一個優(yōu)化_isLabor 值域,_isLabor 在JobItem是值為false,在LaborItem值為true。

可以用多態(tài)常量函數(shù)。所謂「多態(tài)常量函數(shù)」會在不同的subclass 實現(xiàn)版本中返回不同的固定值

class JobItem...protected boolean isLabor() {return false;}class LaborItem...protected boolean isLabor() {return true;}

就可以擺脫_isLabor 值域了

通過多態(tài)代替條件的方式,重構代碼

class JobItem ...public int getUnitPrice(){return (isLabor()) ?_employee.getRate():_unitPrice;}

將它重構為:

class JobItem...public int getUnitPrice(){return _unitPrice;}class LaborItem...public int getUnitPrice(){return _employee.getRate();}

使用某項值域的函數(shù)全被下移至subclass 后,我就可以使用 Push Down Field 將值域也下移。

最后的結果就是:

public class JobItem {protected JobItem (int unitPrice, int quantity) {_unitPrice = unitPrice;_quantity = quantity;}public int getTotalPrice() {return getUnitPrice() * _quantity;}public int getUnitPrice(){return _unitPrice;}public int getQuantity(){return _quantity;}private int _unitPrice;private int _quantity; }// public class LaborItem extends JobItem {private Employee _employee;public LaborItem(int quantity, Employee employee) {super(0, quantity);_employee = employee;}public Employee getEmployee() {return _employee;}public int getUnitPrice() {return _employee.getRate();} }//public class Employee {public Employee(int rate) {_rate = rate;}public int getRate() {return _rate;}private int _rate; }

一個class如果擁有太多代碼,也適合使用Extract Class和Extract Subclass。
想重構代碼,直接把以上四招看情況用上,更多精彩內容,請等待后續(xù)更新。


作者:小虛竹
歡迎任何形式的轉載,但請務必注明出處。
限于本人水平,如果文章和代碼有表述不當之處,還請不吝賜教。

轉載于:https://www.cnblogs.com/zenghw/p/9079541.html

總結

以上是生活随笔為你收集整理的《重构:改善既有代码的设计》-学习笔记一(+实战解析)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。