В пятницу я еще раз просмотрел всю свою кодовую базу, чтобы убедиться, что я избавился от дублирования, насколько это возможно. Я смог удалить большую часть своего дублирования, но, наконец, добрался до двух функций, которые я заметил ранее, но не смог избавиться.

Они были

void options(List<Command> options) {
    StringBuilder instructions = new StringBuilder();
    for (int i = 0; i < options.size(); i++) {
        instructions
                .append(i + 1)
                .append(") ")
                .append(options.get(i).instruction())
                .append(System.lineSeparator());
    }
    output.println(instructions.toString().trim());
}

и

public void selection(List<Player> playerTypes) {
    StringBuilder instructions = new StringBuilder();
    for (int i = 0; i < playerTypes.size(); i++) {
        instructions
                .append(i + 1)
                .append(") ")
                .append(playerTypes.get(i).playerType())
                .append(System.lineSeparator());
    }
    output.println(instructions.toString().trim());
}

Обе эти функции практически идентичны; единственные различия - это тип параметра, который они принимают, и строка, которую они добавляют ( инструкция() или playerType() )

В итоге я создал новый интерфейс под названием Menu, в котором есть только одна функция — title().

public interface Menu {

    String title();
}

Затем мои интерфейсы Player и Command наследуются от Menu. Затем я переименовал инструкции() и playerType() в title() и обновил один из методов на:

public void options(List<? extends Menu> options) {
    StringBuilder instructions = new StringBuilder();
    for (int i = 0; i < options.size(); i++) {
        instructions
                .append(i + 1)
                .append(") ")
                .append(options.get(i).title())
                .append(System.lineSeparator());
    }
    output.println(instructions.toString().trim());
}

Теперь параметр представляет собой список, который расширяет меню (что делают и Command, и Player), и вызывает для него метод title(). Пробовал запускать тесты, все работает.

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

Сегодня я сосредоточусь на том, чтобы дать пользователю возможность играть в формате 4x4, тогда как в настоящее время я поддерживаю только игру 3x3.