第十三计:为集合类型的成员变量提供增删改查函数
对于集合类型的成员变量,直接提供一个函数将其暴露出去是不够妥当的,缺点包括以下几点:
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);
}
第十四计:避免一个临时变量充当多种角色
当在函数中声明一个临时变量的时候,其实已经设定了该变量的角色,这或多或少能从它的命名中看出来,例如下面变量的声明:
String userName = null;
可以看出这个临时变量是存储用户名用的,有些人认为声明多个临时变量会浪费空间,所以在函数中会多次使用该变量,例如用这个变量存储了用户的密码:
userName = “*******”;
这种方式很容易引入Bug,而且降低了可理解性。因此,一个变量应该只充当一种角色。
第十五计:引入NULL Object来避免大量的对象合法性判断
当我们获得对象的引用后,在调用该对象的函数前一般都会检查它是否为NULL来避免程序崩溃,这样也会导致程序中出现大量类似下面的代码段:
EventRecorder recorder = EventRecorderFactory.getRecorderByType(0);
if( recorder ==null ){
Log.error("Recorder对象为空");
lastErrorCode =0;
}
else{
recorder.record("记录点啥...");
}
而NULL Object模式则可以避免这种情况
第十六计:函数命名有语法
大部分函数的命名尽量采用动词+名词的形式,并使其具有自注释性,例如:findUserById,从函数名中不仅能看出函数的功能,甚至连参数也能猜出来,另外,有些命名方式是有一定意义的,例如作为回调的函数一般以on开头,如:onUserPasswordChanged,说明该函数会在用户密码变化时被调用。对于返回布尔值的函数尽量采用疑问句式,如:isNameValid。
第十七计:去除只是内部状态不同的派生类
当某些派生类与父类相比只是状态不同时,那就应该考虑去掉这些派生类,把这些状态作为父类的成员变量,并且可以为原来派生类所表示的对象准备一些构造函数或者工厂方法,例如下面表示员工的类:
public abstract class Employee{
private int id;
private String name;
// 获取薪水
public abstract int getSalary();
// 获取是否有解雇员工的权利
public abstract boolean canFireOthers();
}
public class Programmer extends Employee{
public int getSalary(){
return 5000;
}
public boolean canFireOthers(){
return false;
}
}
public class Manager extends Employee{
public int getSalary(){
return 10000;
}
public boolean canFireOthers(){
return true;
}
}
可以看出,Employee的派生类实质上只是状态与父类不同,应该将它们合并为一个类:
public class Employee{
private int id;
private String name;
private int salary;
private boolean canFireOthers;
public static Employee newProgrammer(String name){
return new Employee(name,5000,false);
}
public static Employee newManager(String name){
return new Employee(name,10000,true);
}
public Employee(String name,int salary,boolean canFireOthers){
this.name = name;
this.salary = salary;
this.canFireOthers = canFireOthers;
}
// 获取薪水
public int getSalary(){
return salary;
}
// 获取是否有解雇员工的权利
public boolean canFireOthers(){
return canFireOthers;
}
}
第十八计:少用标记变量
标记变量一般都是布尔类型的变量,主要用来在某类事件或者操作发生后做个标记,然后其他地方会用到这个标记,用完之后很可能会重置这个标记到初始状态。少量并恰当合理地使用标记变量可以达到很好的效果,能解决一些难题,不过,用的多了就会出乱子,尤其是一个类中有多个成员变量是标记变量,成员函数的实现不得不“看它们的眼色行事“了,它们所产生的标记值的组合会让实现者越来越头大,它们的同时存在增加了程序的复杂性。所以,当类中出现多个标记变量而隐约感觉到不对头时,应该果断干掉它们,然后认真分析处理逻辑是否存在问题,避免再次引入标记变量。
分享到:
相关推荐
重构----改善既有代码的设计(完整中文扫描版PDF)
重构,其实很简单,它的目的就是让程序变得更容易被理解,更具有可维护性,结构更合理。
重构----改善既有代码的设计(By Martin Fowler) 非常经典的一本书!
重构----改善既有代码的设计 怎么写好一个类,怎么重构已有代码,运用多中重构代码的方法,去改善代码结构。
代码重构 C++ 36计 摘抄至http://www.cnblogs.com/west-link/archive/2012/04/16/2446878.html,自行整理出文档,以便后用。
重构不是一项靠着天分挥洒的艺术,而是一项工程。重构是一种有纪律的,经过训练的,有条不紊的程序整理方案,可以将整理过程中不小心引入错误的机率降到最低
参考资料-云服务重构新零售--2017阿里巴巴商业服务生态白皮书.zip
基于Mojolicious框架对pfqq项目进行的重构Mojo-Webqq-master.zip
是一个非常好的讲解重构的资料,简单可读,容易理解,值得朋友们参考
vr技术与信息传播模式重构-网络传播-通信传播.pdf
相空间重构C-C法,含数据 。。
技术重构社会供应链-未来科技趋势白皮书100页.pdf
【面向3D图像重构的100G-FMCW-MIMO雷达】
本书讲述重构,即在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,提高软件的扩展性和维护性。
有色金属行业钴:供需重构,行业反转-20190924-国泰君安-34页.pdf
思想的传承、决裂与重构(上)--《德意志意识形态》创作前史研究.docx
ChatGPT快速流行重构AI商业模式-23020819页.pdf
思想的传承、决裂与重构(上)--《德意志意识形态》创作前史研究(1).docx