如何重构具有多个if-else的代码?

问题描述

我有一堂课,上面有很多“如果不是”。我不知道如何重构它。我考虑过工厂模式,但是我不知道如何实现。有人帮我吗?

    @Override
    public Predicate toPredicate(@NotNull Root<E> root,@NotNull CriteriaQuery<?> cq,@NotNull CriteriaBuilder cb) {

        List<Predicate> predicates = new ArrayList<>();

        for (SearchCriteria criteria : criteriaList) {
            if (criteria.getValue() == null) {
                predicates.add(cb.isTrue(cb.literal(true)));
            } else if (criteria.getoperation().equals(GREATER_THAN)) {
                predicates.add(cb.greaterThan(root.get(criteria.getKey()).as(criteria.getKey().getClass()),criteria.getValue().toString()));
            } else if (criteria.getoperation().equals(LESS_THAN)) {
                predicates.add(cb.lessthan(root.get(criteria.getKey()).as(criteria.getKey().getClass()),criteria.getValue().toString()));
            } else if (criteria.getoperation().equals(GREATER_THAN_EQUAL)) {
                predicates.add(cb.greaterThanorEqualTo(root.get(criteria.getKey()).as(criteria.getKey().getClass()),criteria.getValue().toString()));
            } else if (criteria.getoperation().equals(LESS_THAN_EQUAL)) {
                predicates.add(cb.lessthanorEqualTo(root.get(criteria.getKey()).as(criteria.getKey().getClass()),criteria.getValue().toString()));
            } else if (criteria.getoperation().equals(NOT_EQUAL)) {
                predicates.add(cb.notEqual(root.get(criteria.getKey()).as(criteria.getKey().getClass()),criteria.getValue()));
            } else if (criteria.getoperation().equals(EQUAL)) {
                predicates.add(cb.equal(root.get(criteria.getKey()).as(criteria.getKey().getClass()),criteria.getValue()));
            } else if (criteria.getoperation().equals(MATCH)) {
                predicates.add(cb.like(cb.lower(root.get(criteria.getKey())),"%" + criteria.getValue().toString().toLowerCase() + "%"));
            } else if (criteria.getoperation().equals(MATCH_END)) {
                predicates.add(cb.like(cb.lower(root.get(criteria.getKey())),criteria.getValue().toString().toLowerCase() + "%"));
            } else if (criteria.getoperation().equals(MATCH_START)) {
                predicates.add(cb.like(cb.lower(root.get(criteria.getKey())),"%" + criteria.getValue().toString().toLowerCase()));
            } else if (criteria.getoperation().equals(IN)) {
                predicates.add(cb.in(root.get(criteria.getKey())).value(criteria.getValue()));
            } else if (criteria.getoperation().equals(NOT_IN)) {
                predicates.add(cb.not(root.get(criteria.getKey())).in(criteria.getValue()));
            }
        }
        return cb.and(predicates.toArray(Predicate[]::new));
    }

解决方法

编写SearchCriteria.java界面,如下所示:

public interface SearchCriteria {

    String getOperation();
}

比编写将实现此接口的Criteria类,如下所示:

public class LessThanCriteria implements SearchCriteria {

    public static final String LESS = "some value";

    @Override
    public String getOperation() {
        return LESS;
    }
}

public class GreatherThanCriteria implements SearchCriteria {

    public static final String GREATER_THAN = "some value";

    @Override
    public String getOperation() {
        return GREATER_THAN;
    }
}

ect。

比起编写PredicateFactory.java类,该类封装了用于基于SearchCriteria创建谓词对象的逻辑。

public class PredicateFactory {

    public static final String LESS = "some value";
    public static final String LESS_THAN_EQUAL = "some value";
    public static final String NOT_EQUAL = "some value";
    public static final String EQUAL = "some value";
    public static final String MATCH = "some value";
    public static final String MATCH_END = "some value";
    public static final String MATCH_START = "some value";
    public static final String IN = "some value";
    public static final String NOT_IN = "some value";

    public static Predicate getPredicate(SearchCriteria criteria){
        if(criteria == null){
            return null;
        }
        if(criteria.getOperation().equalsIgnoreCase(LESS)){
            return new Predicate(); // here you create predicate object that 
                                          // you want,//based on criteria

        } else if(criteria.getOperation().equalsIgnoreCase(LESS_THAN_EQUAL)){
            return new Predicate();

        } else if(criteria.getOperation().equalsIgnoreCase(NOT_EQUAL)){
            return new Predicate();
        }
        else if(criteria.getOperation().equalsIgnoreCase(EQUAL)){
             return new Predicate();
        }
        else if(criteria.getOperation().equalsIgnoreCase(MATCH)){
            return new Predicate();
        }
        else if(criteria.getOperation().equalsIgnoreCase(MATCH_END)){
            return new Predicate();
        }
        else if(criteria.getOperation().equalsIgnoreCase(MATCH_START)){
            return new Predicate();
        }
        else if(criteria.getOperation().equalsIgnoreCase(IN)){
            return new Predicate();
        }
        else if(criteria.getOperation().equalsIgnoreCase(NOT_IN)){
            return new Predicate();
        }
        return null;
    }
    
}

最后,在foor循环中使用此Factory类:

for (SearchCriteria criteria : criteriaList) {
      Predicate p = PredicateFactory.getPredicate(criteria);
      predicates.add(p); 

}
,

Factory Pattern是一种创造模式。因此,它用于构造对象,并且各种用途之间需要存在一些公共接口。目前,这并不直接适用于您的情况。

假设您可以编辑CriteriaBuilder,则可以执行以下操作:

  1. (可选)将criteria.getOperation()criteria.getKey()criteria.value()替换为局部变量opkeyvalue,以使代码更具可读性。
  2. 更新CriteriaBuilder,以暴露诸如build(root,key,value,op)之类的单个方法,并将如何构建每个条件的代码移入该方法。
  3. 在您的toPredicate()中,您可以简单地predicates.add(cb.build(root,op))

您可能会争辩说,这种方法只会将巨大的if-else块移至cb.build()方法中;但是,这离更清洁的代码又近了一步。 cb.build()本质上就是您要寻找的工厂方法,而调用方(toPredicate())不必了解建立条件的逻辑。

由于可以直接访问cb.build()中的私有字段,因此可以继续将if-else逻辑改进为CriteriaBuilder。不看CriteriaBuilder的代码就很难说出下一步是什么。