最近看了《重构-改善既有代码的设计》这本书,总结了优化代码的几个小技巧,给你们分享一下。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;
}
复制代码