在调用类似 类 Java 时摆脱 if/else

Getting rid of if/else while calling similar classes Java

我遇到了我想要并且需要摆脱一些 if else 情况的问题。我在我的项目中得到了以下代码:

if (ar[4].equals("week")) {

    WeekThreshold wt = new WeekThreshold();
    firstTime = unparsedDate.format(wt.getStartDate().getTime());
    secondTime = unparsedDate.format(wt.getEndDate().getTime());

} else if (ar[4].equals("month")) {

    MonthThreshold mt = new MonthThreshold();
    firstTime = unparsedDate.format(mt.getStartDate().getTime());
    secondTime = unparsedDate.format(mt.getEndDate().getTime());

} else if (ar[4].equals("quarter")) {

    quarterThreshold();

} else if (ar[4].equals("year")) {

    YearThreshold yt = new YearThreshold();
    firstTime = unparsedDate.format(yt.getStartDate().getTime());
    secondTime = unparsedDate.format(yt.getEndDate().getTime());
}

这三个 classes WeekThresholdMonthThresholdYearThresholdAbstractThreshold class 扩展,它们从日历中获取日期,但这并不重要。方法quarterThreshold()比较特殊,可以留在那里。但是我怎样才能摆脱 if else 块并有一个语句来调用不同的 classes?

编辑:忘了说,需要调用的classes来自数组ar[]的各种类型。如果数组ar[4]是月份,则必须调用MonthThreshold

多种可能性... XYZThreshold classes 是否具有通用接口,如 Threshold?然后你可以用它分配一个变量,例如...

Threshold threshold = null;
if ((ar[4].equals("week")) {
  threshold = new WeekThreshold();
} else ... {

}

firstTime = unparsedDate.format(threshold.getStartDate().getTime());
secondTime = unparsedDate.format(threshold.getEndDate().getTime());

这将是第一步。如果你愿意,你可以,例如,使用枚举来存储你的阈值:

enum Thresholds {
  WEEK("week") {

     public Threshold getThreshold() {
           return new WeekThreshold();
     }
  },
  etc.

  private String period;

  private Thresholds(String period) {
    this.period = period;
  }

  public abstract Threshold getThreshold();

  //  ...add a static class to iterate and search by period, 
  // ...so you can write Threshold threshold = Thresholds.getByPeriod("week").getThreshold();
}

使用枚举是个人喜好,当然,您可以使用普通的 classes 做同样的事情,或者简单地将用于阈值选择的 if 块放入单独的 class .

你可以像这样在外部合并公共代码(unparsedDate.format(...)):

AbstractThreshold at = null;
switch(ar[4]) {
case "week":
    at = new WeekThreshold();
    break;
case "month":
    at = new MonthThreshold();
    break;
case "year":
    at = new YearThreshold();
    break;
case "quarter":
    quarterThreshold();
    break;
}
if(at != null) {
    firstTime = unparsedDate.format(at.getStartDate().getTime());
    secondTime = unparsedDate.format(at.getEndDate().getTime());
}

当然,过度设计的版本是可能的。这里只是说明如何使用 Java-8 功能实现它:

// Map can be initialized only once, then used many times
Map<String, Supplier<AbstractThreshold>> thresholdSuppliers = new HashMap<>();
thresholdSuppliers.put("week", WeekThreshold::new);
thresholdSuppliers.put("month", MonthThreshold::new);
thresholdSuppliers.put("year", YearThreshold::new);

AbstractThreshold at = thresholdSuppliers.getOrDefault(ar[4], () -> null).get();
if(at != null) {
    firstTime = unparsedDate.format(at.getStartDate().getTime());
    secondTime = unparsedDate.format(at.getEndDate().getTime());
} else if(ar[4].equals("quarter"))
    quarterThreshold();
}

你可以使用 switch 语句

String typeOfDay;
     switch (dayOfWeekArg) {
         case "Monday":
             typeOfDay = "Start of work week";
             break;
         case "Tuesday":
         case "Wednesday":
         case "Thursday":
             typeOfDay = "Midweek";
             break;
         case "Friday":
             typeOfDay = "End of work week";
             break;
         case "Saturday":
         case "Sunday":
             typeOfDay = "Weekend";
             break;
         default:
             throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
     }

您可以将我从 java 文档中窃取的示例替换为您自己的代码

switch(periodType){
    case "week":
      WeekThreshold wt = new WeekThreshold();
    break; // add your other cases
}
firstTime = unparsedDate.format(wt.getStartDate().getTime());
secondTime = unparsedDate.format(wt.getEndDate().getTime());

这里可以好好利用工厂模式

class ThresholdFactory
{
  public static AbstractThreshold getThreshold(String criteria)
  {
    if ( criteria.equals("week") )
      return new WeekThreshold();
    if ( criteria.equals("month") )
      return new MonthThreshold();
    if ( criteria.equals("year") )
      return new YearThreshold();

    return null;
  }
}

其余代码如下所示:

AbstractThreshold at = ThresholdFactory.getThreshold(ar[4]);
if(at != null){
  firstTime = unparsedDate.format(at.getStartDate().getTime());
  secondTime = unparsedDate.format(at.getEndDate().getTime());
} else {
   quarterThreshold();
}

这里有一个如何使用接口和工厂设计模式的例子 如果您的多个实现者共享公共代码,请让它们都扩展一个实现该接口的抽象 class。通过接口引用你的方法是个好主意,而不是具体的 class 以利用多态性......见下面的代码......

public class Example {

    public static void main(String[] args) {

        String[] intervals = {"week", "week", "quarter", "month", "year", "week"}; 

        IThreshold[] objects = new IThreshold[intervals.length];

        // Create your objects using Factory pattern
        for(int index = 0; index < intervals.length; index++) {
            objects[index] = ThresholdFactory.createInstance(intervals[index]);
        }

        // Now iterate through your objects and refer to them through a common interface
        for(IThreshold object : objects) {
            int start = object.getFirstTime();
            int end = object.getFirstTime();
        }
    }
}

interface IThreshold {
    public int getFirstTime();
    public int getLastTime();
}


abstract class AbstractThreshold implements IThreshold {

    @Override
    public int getFirstTime() {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public int getLastTime() {
        // TODO Auto-generated method stub
        return 0;
    }

}

class WeekThreshold extends AbstractThreshold {}
class MonthThreshold extends AbstractThreshold {}
class QuarterThreshold extends AbstractThreshold {}
class YearThreshold extends AbstractThreshold {}

class ThresholdFactory {

    public static final IThreshold createInstance(String interval) {
        IThreshold instance = null;

        if(interval.equals("week")){
            instance = new WeekThreshold();
        } 
        else if(interval.equals("month")){
            instance = new MonthThreshold();
        } 
        else if(interval.equals("quarter")){
            instance = new QuarterThreshold();
        } 
        else {
            if(interval.equals("year")){
                instance = new YearThreshold();
            }
        }
        return instance;
    }
}

首先创建门槛工厂,

static enum ThresholdsFactory {


        week(new WeekThreshold()), month(new MonthThreshold())/* etc */;

        static private Map<String,ThresholdsFactory> lookup = new HashMap<String, ThresholdsFactory>();
        static{
            for(ThresholdsFactory val :  ThresholdsFactory.values()){
            lookup.put(val.name(), val);
            }
        }

        public AbstractThreshold threshold;

        public static ThresholdsFactory find(String name){
            return lookup.get(name);
        }

        ThresholdsFactory(AbstractThreshold th) {
            threshold = th;

} }

现在您需要做的就是

AbstractThreshold th = ThresholdsFactory.find(ar[4]);

if (th!=null){
    firstTime = unparsedDate.format(th.getStartDate().getTime());
    secondTime = unparsedDate.format(th.getEndDate().getTime());
}