您的位置:首页 > 编程语言 > Java开发

Java枚举的使用以及几种解决if else引起的代码不可维护的方案

2017-09-11 17:18 411 查看
在说枚举之前先来举个例子,我们都知道发表的csdn博客都需要审核,那么审核的状态就有这么几种:审核中、审核通过、审核不通过(假设目前的需求就要求有这么三种状态)。那么我们可以在项目里这么写

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吧
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐