最近看了《重構-改善既有代碼的設計》這本書,總結了優化代碼的幾個小技巧,給你們分享一下。bash
提煉函數就是將一段代碼放進一個獨立函數中,並讓函數名稱解釋該函數用途。函數
一個過於冗長的函數或者一段須要註釋才能讓人理解用途的代碼,能夠考慮把它切分紅一個功能明確的函數單元,並定義清晰簡短的函數名,這樣會讓代碼變得更加優雅。學習
提煉函數以前:優化
private String name;
private Vector<Order> orders = new Vector<Order>();
public void printOwing() {
//print banner
System.out.println("****************");
System.out.println("*****customer Owes *****");
System.out.println("****************");
//calculate totalAmount
Enumeration env = orders.elements();
double totalAmount = 0.0;
while (env.hasMoreElements()) {
Order order = (Order) env.nextElement();
totalAmount += order.getAmout();
}
//print details
System.out.println("name:" + name);
System.out.println("amount:" + totalAmount);
}
複製代碼
提煉函數以後:ui
以上那段代碼,能夠抽成print banner,calculate totalAmount,print details三個功能的單一函數,以下:spa
private String name;
private Vector<Order> orders = new Vector<Order>();
public void printOwing() {
//print banner
printBanner();
//calculate totalAmount
double totalAmount = getTotalAmount();
//print details
printDetail(totalAmount);
}
void printBanner(){
System.out.println("****************");
System.out.println("*****customer Owes *****");
System.out.println("****************");
}
double getTotalAmount(){
Enumeration env = orders.elements();
double totalAmount = 0.0;
while (env.hasMoreElements()) {
Order order = (Order) env.nextElement();
totalAmount += order.getAmout();
}
return totalAmount;
}
void printDetail(double totalAmount){
System.out.println("name:" + name);
System.out.println("amount:" + totalAmount);
}
複製代碼
內聯函數就是在函數調用點插入函數本體,而後移除該函數。設計
上一小節介紹了提煉函數代碼優化方式,以簡短清晰的小函數爲榮。可是呢,小函數是否是越多越好呢?確定不是啦,有時候你會遇到某些函數,其內部代碼和函數名稱一樣清晰,這時候呢你能夠考慮內聯函數優化一下了。code
內聯函數以前orm
int getRating(){
return moreThanFiveDeliveries() ? 2 : 1;
}
boolean moreThanFiveDeliveries(){
return numberOfLateDeliveries >5;
}
複製代碼
內聯函數以後cdn
int getRating(){
return numberOfLateDeliveries >5 ? 2 : 1;
}
複製代碼
內聯臨時變量將全部對該變量的引用動做,替換爲對它賦值的那個表達式自身。
內聯臨時變量以前
double basePice = anOrder.basePrice();
return basePice >888;
複製代碼
內聯臨時變量以後
return anOrder.basePrice() >888;
複製代碼
引入解釋性變量 就是將該複雜表達式(或其中一部分)的結果放進一個臨時變量,以此變量名稱來解釋表達式用途。
有些表達式可能很是複雜難於閱讀,在這種狀況下,臨時變量能夠幫助你將表達式分解爲可讀的形式。
在比較複雜的條件邏輯中,你能夠用引入解釋性變量將每一個條件子句提煉出來,以一個良好命名的臨時變量來解釋對應條件子句的意義。
引入解釋性變量以前
if ((platform.toUpperCase().indexOf("mac") > -1) &&
(brower.toUpperCase().indexOf("ie") > -1) &&
wasInitializes() && resize > 0) {
......
}
複製代碼
引入解釋性變量以後
final boolean isMacOS = platform.toUpperCase().indexOf("mac") > -1;
final boolean isIEBrowser = brower.toUpperCase().indexOf("ie") > -1;
final boolean wasResized = resize > 0;
if (isMacOS && isIEBrowser && wasInitializes() && wasResized) {
......
}
複製代碼
創造一個常量,根據其意義爲它命名,並將上述的字面數值替換爲這個常量。
所謂魔法數是指擁有特殊意義,卻又不能明確表現出這種意義的數字。若是你須要在不一樣的地點引用同一個邏輯數,每當該數字要修改時,會特別頭疼,由於極可能會改漏。而字面常量取代魔法數能夠解決這個頭疼問題。
以字面常量取代魔法數以前
double getDiscountPrice(double price){
return price * 0.88;
}
複製代碼
以字面常量取代魔法數以後
static final double DISCOUNT_CONSTANT=0.88;
double getDiscountPrice(double price){
return price * DISCOUNT_CONSTANT;
}
複製代碼
用多態替換switch語句 就是利用Java面向對象的多態特色,使用state模式來替換switch語句。
用多態替換switch語句以前
int getArea() {
switch (shape){
case SHAPE.CIRCLE:
return 3.14 * _r * _r; break;
case SHAPE.RECTANGEL;
return width *,heigth;
}
}
複製代碼
用多態替換switch語句以後
class Shape {
int getArea(){};
}
class Circle extends Shape {
int getArea() {
return 3.14 * r * r;
}
}
class Rectangel extends Shape {
int getArea() {
return width * heigth;
}
}
複製代碼
將過多的參數對象化就是把涉及過多參數封裝成一個對象傳參。
一個方法有太多傳參時,即難以閱讀又難於維護。尤爲針對dubbo遠程調用這些方法,若是有過多參數,增長或者減小一個參數,都要修改接口,真的坑。若是把這些參數封裝成一個對象,就很好維護了,不用修改接口。
將過多的參數對象化以前:
public int register(String username,String password,Integer age,String phone);
複製代碼
將過多的參數對象化以後:
public int register(RegisterForm from );
class RegisterForm{
private String username;
private String password;
private Integer age;
private String phone;
}
複製代碼