再看博文 重构36计 http://blog.csdn.net/m13666368773/article/details/7472201,将觉得有用的摘抄过来。
第一计:参数列表对象化
公有函数的参数应尽可能保持不变,因为很多地方都会调用它,修改参数后需要修改它的调用处,另外,它的参数列表不宜过长,数量尽量保持在5个以内,长参数列表会增加该函数的调用难度。对于参数较多或者参数经常变化的公有函数,较好的办法是引入参数对象,即该函数的参数只有一个,它就是参数对象,具体的参数都在该对象中声明,为函数引入参数对象有以下几个好处:
1、保持函数接口的不变性,修改函数参数只需修改参数对象中的成员变量。
2、调用方便,调用方不用再关心参数的顺序。
以下代码片段是一个添加用户函数的声明:
public long insertUser(String name,int age,String email,String address,String phone,String birthDay)
每当添加或删除用户的字段后都要修改insertUser的参数列表,调用者也需要修改,而且参数较多时,不容易记忆。
以下是引入参数对象后的形式:
public class UserParam{ public String name; public int age; public String email; public String address; public String phone; public String birthDay; } public long insertUser(UserParam user);
第五计:消灭魔法数
编程新手一般都会直接将表示类型或状态的数字直接写在处理逻辑中,代码的作者能明白该数字所表示的含义,但其他人读到这段代码时就很有可能看不懂了。即使代码的作者再过一段时间来看这部分代码,也可能会忘记该数字的含义,而且,当我们要修改魔法数的值时,过程是很繁琐的,很有可能会有所遗漏,所以,最好的办法是彻底消灭程序中的所有魔法数,通过常量定义、枚举等方式来避免魔法数的出现。
第七计:串联函数调用
当一个类的大部分函数被较为频繁地调用,并且包含连续性地调用,那么可以考虑为这个类中那些没有返回值的函数增加返回值,即返回对象本身,这样就可以串联函数调用,使用起来较为方便,举个例子:
// 表示用户的类 public class User{ public void setName(String name); public void setAge(int age); public void setPhoneNumber(int phoneNumber); }
下面是不使用串联函数调用的情况:
User user = new User(); user.setName("West_Link"); user.setAge(3); user.setPhoneNumber(122333);
下面是使用串联函数调用的情况:
User user = new User().setName("West_Link").setAge(3).setPhoneNumber(123333);
只需要为那些函数增加一个User对象的返回值即可,如下:
public User setName(String name){ this.name = name; return this; }
第十二计:循环中早用continue减少条件嵌套
除了通过合并条件来减少嵌套层次外,在for或者while循环中,可以用continue来减少条件嵌套,例如:
for(int i=0; i<100;i++){ if(a){ if(b){ if(c){ ... } } } }
这段代码的嵌套深度是4,使用continue可以大大减少嵌套层次:
for(int i=0; i<100;i++){ if(!a) continue; if(!b) continue; if(!c) continue; ... }
第十三计:为集合类型的成员变量提供增删改查函数
对于集合类型的成员变量,直接提供一个函数将其暴露出去是不够妥当的,缺点包括以下几点:
1、添加集合元素时无法校验它的合法性,例如类型是否符合要求、该元素是否已存在等。
2、无法控制集合的容量,集合的容量可能是动态分配的。
所以,更好的做法是为集合类型的成员变量提供增删改查等函数,例如某个类中有名为userList的数组,则可以为它增加几个函数:
public void add(User user){ if(user == null) // 如果对象为不合法,则不添加 return; if(userList == null) // 如果集合还未初始化,则新建 userList = new ArrayList(); if(isUserExisted(user)) // 如果该用户已经存在,则不添加 return; // 将该用户添加到集合中 userList.add(user); } public void delete(User user){ if(userList == null) return; userList.remove(user); }
第二十二计:用自注释性变量代替复杂条件
嵌套层次较深的IF判断、没有注释的复杂条件大大增加了程序的逻辑复杂性,严重降低代码的可读性。对于子条件较多的条件判定,可以为各个子条件引入具有自注释性的临时变量来降低复杂性。例如下面是判断登录用户是否能进入网站的后台管理界面:
if(userName!=null && userName.equals(name) && (userState != INACTIVE || userState != DELETE) && userPassword!=null && userPassword.equals(password) && (userGroup == "Manager" || userGroup == "Root")){ ... }
下面是修改后的版本:
boolean isUserNameValid = userName!=null && userName.equals(name); boolean isUserActive = userState != INACTIVE || userState != DELETE; boolean isUserPasswordCorrect = userPassword!=null && userPassword.equals(password); boolean isUserHasAuth = userGroup == "Manager" || userGroup == "Root"; if(isUserNameValid && isUserActive && isUserPasswordCorrect && isUserHasAuth){ ... }
第二种方式不仅使条件判断更具有可读性,还能重用子条件。
第三十三计:简化类关系
如果类之间的关系比较复杂,那么很可能是面向对象的设计没有做好。一般来说,两个类之间有双向调用关系则说明它们在职责上的分配上不够清晰,例如,一个类(A)频繁地调用另一个类(B)的函数,而且A还把成员变量作为参数传递给B,那么大部分情况下就应该把那个函数定义在A中,从而切断两者之间的关系。另外,系统中有很多类对某些类的状态变化或者事件感兴趣,例如添加一个新用户、网络状态的变化等,对于这样的需求,最好通过各种消息机制来达到它们之间的解耦,如观察者模式、发布订阅模式等。发布订阅模式可以参见这篇文章:GoF著作中未提到的设计模式(7):Publish-Subscribe