Java枚举的使用以及几种解决if else引起的代码不可维护的方案
2017-09-11 17:18
411 查看
在说枚举之前先来举个例子,我们都知道发表的csdn博客都需要审核,那么审核的状态就有这么几种:审核中、审核通过、审核不通过(假设目前的需求就要求有这么三种状态)。那么我们可以在项目里这么写
但是这样的硬编码只是图个方便,还是有很大的问题的。万一哪天需要改变状态的标识,用0来表示审核不通过,或者需求改变,需要增加、删除状态的时候,那就不得不改变所有与审核状态有关的代码,这个工作量无疑是巨大的,如果是庞大的项目,肯定是会有遗漏的。
好,既然这种硬编码不行,我们很快就能想到用静态常量(或者用配置文件)来表示审核的状态
这样的写法很好的解决了改变状态标识引发的问题,当标识改变时,只需修改常量类就行,而不用修改整个项目所有涉及到状态标识的地方。但是当项目需求改变,需要新加一种未审核状态,你除了在常量类新加一个变量,还需要在所有的相关代码中加一个else if,这显然也是不科学的。当然,你可以重构你的代码,不使用这种if else来判断你的逻辑。方法还是挺多的,下面就简单介绍几种。
1.使用多态:
当新加一种状态,只要在match方法中加上具体的逻辑,而不用向之前那样在所有涉及到的地方进行修改。我们可以发现,以上的代码只适合一种业务逻辑,比如说在你的项目中,所有的判断都是根据状态显示不同颜色的:博客状态是审核中的,颜色显示红色,是审核通过的,颜色显示黑色。但是如果在你的项目中有多种业务逻辑,一处逻辑是根据状态显示不同的颜色,一处逻辑是根据状态显示不同的信息,那么以上的代码就不适用了,需要稍加修改。给method方法添加参数来调用不同的业务逻辑。
2.如果多态需要创建的类太多,可以使用枚举:根据不同的状态显示不同的文字和颜色
从以上代码可以看出,当需求改变时,我们只需要在枚举类中进行简单修改,而不用在所有涉及到的代码中修改。
其实还有很多方法可以规避大量if else带来的问题,至于用哪种方法还是看你具体使用的场景。在你的项目中仅仅只有一处地方用到了if else,那么用if else又有何不可呢,反正以后需求改变,你也知道去什么地方修改。也有的程序员就是不喜欢用枚举,喜欢用常量,觉得枚举又要消耗性能,又不能继承不能扩展,还是常量用起来简单方便,在不追求代码扩展性,不考虑类型安全的前提下,那就用呗。当然如果在系统升级阶段,需要改变常量值,就要重新编译,在这点上用常量是不如用配置文件或者xml的;相反的,有的程序员就是不喜欢常量,喜欢枚举,又不是有很多地方用到枚举,那么牺牲一点性能换来代码的可维护又何尝不可呢。当用的枚举越来越多,考虑到性能的时候,就要用多态或者其他什么方法来替代枚举
好,现在终于可以步入正题,介绍枚举的使用了。哈哈哈哈哈…
这里定义的Season本身是一个类,并且存在四个实例(不是字符串),可以直接打印Season.SPRING这个实例
两个枚举类型的值比较可以直接用“==”,而不是必须用equals
可以在枚举类中添加构造器、方法和域。在这里,这四个实例SPRING,SUMMER,FALL,WINTER已经调用了四次默认的构造函数Season()
非抽象的枚举类默认使用final修饰,因此枚举类不能被继承
枚举类也不能继承其他的类,因为java是单一继承,他已经继承了java.lang.Enum
枚举类是单例的,所以他的构造器默认是private的,也必须是private的(可以不写)
枚举类的所有实例必须在第一行显示列出,并且系统会自动用 public static final修饰
对于枚举类的遍历可以用values()方法,Season []seasons = Season.values(),具体可以参照上面的代码
toString:返回枚举常量名。Season.SPRING.toString()将返回字符串”SPRING”
valueOf:toString的逆方法,将字符串变为枚举类型
ordinal:返回枚举常量在枚举声明中的位置,位置从0开始计数。Season.SPRING.ordinal()返回0
还有其他的方法具体就参考api吧
if(state == 1){ //1表示审核中 MethodA(); }else if(state == 2){ //2表示审核通过 MethodB(); }else if(state == 3){ //3表示审核不通过 MethodC(); }
但是这样的硬编码只是图个方便,还是有很大的问题的。万一哪天需要改变状态的标识,用0来表示审核不通过,或者需求改变,需要增加、删除状态的时候,那就不得不改变所有与审核状态有关的代码,这个工作量无疑是巨大的,如果是庞大的项目,肯定是会有遗漏的。
好,既然这种硬编码不行,我们很快就能想到用静态常量(或者用配置文件)来表示审核的状态
public static final int AUDITING = 1; //审核中 public static final int AUDIT = 2; //审核通过 public static final int UNAUDIT = 3; //审核不通过 if(state == AUDITING){ MethodA(); }else if(state == AUDIT){ MethodB(); }else if(state == UNAUDIT){ MethodC(); }
这样的写法很好的解决了改变状态标识引发的问题,当标识改变时,只需修改常量类就行,而不用修改整个项目所有涉及到状态标识的地方。但是当项目需求改变,需要新加一种未审核状态,你除了在常量类新加一个变量,还需要在所有的相关代码中加一个else if,这显然也是不科学的。当然,你可以重构你的代码,不使用这种if else来判断你的逻辑。方法还是挺多的,下面就简单介绍几种。
1.使用多态:
//基类: abstract public class Base{ abstract public void method(); } //审核中 public class Auditing extends Base{ public void method(){ ... } } //审核通过 public class Audit extends Base{ public void method(){ ... } } //审核不通过 public class UnAudit extends Base{ public void method(){ ... } } //业务功能 public static void main(String[] args) { //从数据库获取状态,并赋给变量state Base base = match(state); base.method(); } private static Base match(int state) { if(state == AUDITING){ return new Auditing(); }else if(state == AUDIT){ return new Audit(); }else if(state == UNAUDIT){ return new UnAudit(); } }
当新加一种状态,只要在match方法中加上具体的逻辑,而不用向之前那样在所有涉及到的地方进行修改。我们可以发现,以上的代码只适合一种业务逻辑,比如说在你的项目中,所有的判断都是根据状态显示不同颜色的:博客状态是审核中的,颜色显示红色,是审核通过的,颜色显示黑色。但是如果在你的项目中有多种业务逻辑,一处逻辑是根据状态显示不同的颜色,一处逻辑是根据状态显示不同的信息,那么以上的代码就不适用了,需要稍加修改。给method方法添加参数来调用不同的业务逻辑。
2.如果多态需要创建的类太多,可以使用枚举:根据不同的状态显示不同的文字和颜色
//枚举类 public enum EnumState{ UNMATCH(-1,"不匹配","#FFFFFF"), AUDITING(1,"审核中","#FFFFFF"), AUDIT(2,"审核通过","#FFFFF0"), UNAUDIT(3,"审核未通过","#FFFAFA"); private int identify; private String wordInfo; private String color; EnumState(int identify,String wordInfo,String color){ this.identify = identify; this.wordInfo = wordInfo; this.color = color; } public static EnumState getState(int state){ for (EnumState eachState : values()) { if(state == eachState.identify){ return eachState; } } return UNMATCH; } public int getIdentify() { return identify; } public void setIdentify(int identify) { this.identify = identify; } public String getWordInfo() { return wordInfo; } public void setWordInfo(String wordInfo) { this.wordInfo = wordInfo; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } } //实际的业务代码 从数据库获取state EnumState enumState = EnumState.getState(state);
从以上代码可以看出,当需求改变时,我们只需要在枚举类中进行简单修改,而不用在所有涉及到的代码中修改。
其实还有很多方法可以规避大量if else带来的问题,至于用哪种方法还是看你具体使用的场景。在你的项目中仅仅只有一处地方用到了if else,那么用if else又有何不可呢,反正以后需求改变,你也知道去什么地方修改。也有的程序员就是不喜欢用枚举,喜欢用常量,觉得枚举又要消耗性能,又不能继承不能扩展,还是常量用起来简单方便,在不追求代码扩展性,不考虑类型安全的前提下,那就用呗。当然如果在系统升级阶段,需要改变常量值,就要重新编译,在这点上用常量是不如用配置文件或者xml的;相反的,有的程序员就是不喜欢常量,喜欢枚举,又不是有很多地方用到枚举,那么牺牲一点性能换来代码的可维护又何尝不可呢。当用的枚举越来越多,考虑到性能的时候,就要用多态或者其他什么方法来替代枚举
好,现在终于可以步入正题,介绍枚举的使用了。哈哈哈哈哈…
public enum Season{ SPRING,SUMMER,FALL,WINTER; }
这里定义的Season本身是一个类,并且存在四个实例(不是字符串),可以直接打印Season.SPRING这个实例
两个枚举类型的值比较可以直接用“==”,而不是必须用equals
Season s1 = Enum.valueOf(Season.class, "SPRING"); Season s2 = Enum.valueOf(Season.class, "SPRING"); System.out.println(s1 == s2); //true
可以在枚举类中添加构造器、方法和域。在这里,这四个实例SPRING,SUMMER,FALL,WINTER已经调用了四次默认的构造函数Season()
非抽象的枚举类默认使用final修饰,因此枚举类不能被继承
枚举类也不能继承其他的类,因为java是单一继承,他已经继承了java.lang.Enum
枚举类是单例的,所以他的构造器默认是private的,也必须是private的(可以不写)
枚举类的所有实例必须在第一行显示列出,并且系统会自动用 public static final修饰
对于枚举类的遍历可以用values()方法,Season []seasons = Season.values(),具体可以参照上面的代码
toString:返回枚举常量名。Season.SPRING.toString()将返回字符串”SPRING”
valueOf:toString的逆方法,将字符串变为枚举类型
ordinal:返回枚举常量在枚举声明中的位置,位置从0开始计数。Season.SPRING.ordinal()返回0
还有其他的方法具体就参考api吧
相关文章推荐
- HessianCSharp 1.3.3版本前使用泛型以及接口interface继承问题解决方案!!(实例代码)
- 使用SQLCipher进行数据库加密代码实现以及java.lang.UnsatisfiedLinkError 报错的解决
- Java中几种输出数组的for循环,以及循环中使用标签(非goto)
- XP系统的电源使用方案显示灰色(不可使用)的解决办法
- 在Java中实现.net中DataTable功能以及操作双数据库的List连接问题解决方案探究
- [转]在Java中实现.net中DataTable功能以及操作双数据库的List连接问题解决方案探究
- 在Java中实现.net中DataTable功能以及操作双数据库的List连接问题解决方案探究
- 提高你的Java代码质量吧:推荐使用枚举定义常量
- [编写高质量代码:改善java程序的151个建议]建议83 推荐使用枚举定义常量
- 使用网上流传的一个数据库连接池在Proxy.newProxyInstance处引起 java.lang.ClassCastException 问题的解决方法
- [编写高质量代码:改善java程序的151个建议]建议91 枚举和注解结合使用威力更大
- Java路径问题最终解决方案使用演示
- [编写高质量代码:改善java程序的151个建议]建议84 使用构造函数协助描述枚举项
- 黑马程序员_eclipse的使用和java1.5新特性以及枚举
- Java路径问题最终解决方案使用演示
- 【郭林专刊】如何使用TortoiseSVN(例如远程维护代码),请详细说明它的使用过程,包括它的配置,以及使用条件
- 使用Eclipse运行Java代码调用JDBC读写MySQL中文变成问号的终极解决办法
- java---javadoc---Eclipse中javadoc的使用以及中文乱码的解决
- 使用Eclipse运行Java代码调用JDBC读写MySQL中文变成问号的终极解决办法