Enum vs If-else

时间:2015-10-29 06:21:06

标签: java

我有一个要求,我需要在事件列表中构建如下的员工对象。目前我已经编写了如下代码,但QE发表评论说可能使用枚举而不是多个if else。 有人可以建议我如何使用枚举实现这一目标。

Employee e= new Employee();
for(Event event:events){
if("empid".equals(event.getName())
   e.setEmployeeId(event.getvalue());
else if("empname".equals(event.getName())
   e.setEmployeeName(event.getvalue());
else if("empsal".equals(event.getName())
   e.setEmployeeSal(event.getvalue());
else if("empdob".equals(event.getName())
   e.setEmployeeDOB(event.getvalue());
else if("emprole".equals(event.getName())
   e.setEmployeeRole(event.getvalue());
}

3 个答案:

答案 0 :(得分:2)

使用以下代码创建枚举

public enum  EMPLOYEE_FIELDS {EMPID, EMPNAME,EMPSAL, EMPDOB, EMPROLE};

EMPLOYEE_FIELDS empField = EMPLOYEE_FIELDS.valueOf(event.getName().toUpperCase());

 switch(empField ){
    case EMPID:
        //do something here
        break;
    case EMPNAME:
        //do something here
        break;
    // other cases.
    // other cases.
    // other cases.
    default:
            //do something here
 }

希望这有帮助!

答案 1 :(得分:2)

我建议你将事件的逻辑移到enum。如果您使用的是Java 8,那么它看起来像是:

enum EmployeeField {
    ID("empid", Employee::setEmployeeID),
    NAME("empname", Employee::setEmployeeName),
    SALARY("empsalary", Employee::setEmployeeSalary),
    ...

    private final String key;
    private final BiConsumer<Employee, String> valueSetter;

    EmployeeField(String key, BiConsumer<Employee, String> valueSetter) {
        this.key = key;
        this.valueSetter = valueSetter;
    }

    public void setEmployeeField(Employee employee, String value) {
        valueSetter.accept(employee, value);
    }

    public static EmployeeField getFieldForKey(String key) {
        return Arrays.stream(values[])
            .filter(ef -> ef.key.equals(key))
            .findAny()
            .orElseThrow(new IllegalArgumentException("No employee field " + key));
    }
}

然后你可以完全免除switch语句,只需使用:

events.stream()
    .forEach(ev -> EmployeeField.getFieldForKey(ev.getName())
        .setEmployeeField(emp, ev.getValue()));

这也意味着有关员工字段的所有信息(包括如何设置员工价值)都封装在枚举中,可以轻松更改或扩展,而不会受到其他任何影响。

请注意,您可以在不使用lambdas之前在Java 8之前执行类似的操作,但它不像在我的视图中那样优雅,因为匿名接口实例需要变得明确,这会使代码变得更加复杂。或者你可以覆盖每个枚举成员的方法(在我看来)甚至更丑。

答案 2 :(得分:2)

如果您掌控Event的开发,​​我相信您的QE说的是用enum替换事件名称(这是一个理智的设计,因为您已经决定了什么是可能的事件类型)。但是,如果Event的设计不受您的控制,或者您无法使用Event的子类供您使用(例如制作EmployeeEvent),那么请忽略我的意思要说)

即。

enum EventType {
    EMP_ID,
    EMP_NAME,
    ....
}


interface Event {
    EventType getType();   // instead of getName() which returns a String
}

然后您的代码可以简化为

Employee e= new Employee();
for (Event event: events) {
    switch (event.getType()) {
        case EMP_ID:
            e.setEmployeeId(event.getvalue());
            break;
        case EMP_NAME:
            e.setEmployeeName(event.getvalue());
            break;
        ....
    }
}

您甚至可以使用地图预设针对每种事件类型执行的操作(与其他答案的概念类似)

Map<EventType, BiConsumer<Employee, String>> eventActions = new EnumMap<>();
eventActions.put(EventType.EMPLOYEE_ID, Employee::setEmployeeID);
eventActions.put(EventType.EMPLOYEE_NAME, Employee::setEmployeeName);

因此您可以通过以下方式进一步简化上述转换:

Employee e= new Employee();
for (Event event: events) {
    eventActions.get(event.getType()).accept(e, event.getValue()));
}