Улучшите многие ifs, которые возвращают перечисление с шаблонами проектирования

#design-patterns #code-cleanup

Вопрос:

Конечно, когда мы говорим о количестве «если», мы стараемся использовать шаблон Стратегии. Но как насчет того, когда я хочу разделить условия внутри if().

Например, я разрабатываю игру со многими возможностями:

У меня есть занятие под названием «Игра». Я проверяю метод и возвращаю перечисление.

 if(TieByPoints()) {
  return Result.TieByPoints;
}
if(TieByTimeOver()) {
  return Result.TieByTimeOver;
}
if(JustOnePlayerWin()) {
  return Result.PlayerWin;
}
if(ManyPlayersWin()) {
  return Result.PlayerWin;
}
 

Но можно создать множество других возможностей/правил.
Итак, есть ли способ разделиться на разные классы? Поставить эти условия в разных местах?

Комментарии:

1. В чем проблема, которую вы пытаетесь решить, или запах кода, который вы хотите устранить? Это поможет, если вы сможете объяснить, что вам не нравится в этом коде.

2. Если появятся новые правила, я должен буду создать новые условия if. Итак, есть ли способ избежать этого?

Ответ №1:

Вы не объяснили достаточно подробностей, чтобы сказать с уверенностью, но одним из подходов было бы использование шаблона реестра, в котором в реестре хранятся производители результатов.

Что-то вроде

 public enum Result { None, TieByPoints, ... };

public class ResultSupplierRegistry {
  /** Singleton instance of registry. */
  public static final ResultProducerRegistry INSTANCE = new ResultSupplierRegistry();

  private final Map<Result, Supplier<Boolean>> resultSuppliers = new HashSet<>();

  private ResultSupplierRegistry() {}

  public void register(Result result, Supplier<Boolean> resultSupplier) {
    resultSuppliers.put(result, resultSupplier);
  }

  public Result getResult() {
    return resultSuppliers.entrySet().stream().filter(e -> e.getValue().get()).map(Entry::getKey).findFirst().orElse(Result.None);
  }
}
 

Теперь вам нужна некоторая инициализация для заполнения реестра. Я не принял здесь никаких мер предосторожности по безопасности потоков. Если инициализация может выполняться несколькими потоками, вам нужно будет это исправить.

Комментарии:

1. Отлично! Я никогда об этом не думал. Спасибо.