Как переписать обработку разных типов документов более элегантно
Что проверяют
Видите ли вы, что длинный if или switch по типу документа это место, которое правится при каждом новом типе, и умеете ли заменить его расширяемой конструкцией. Следом обычно спрашивают, как выбрать между полиморфизмом и switch по sealed-иерархии в современной Java.
Как отвечать
Сначала назовите проблему: логика всех типов в одном методе, новый тип требует правки работающего кода, тесты растут вместе с методом. Потом варианты:
- стратегия с реестром: интерфейс
DocumentHandlerс методамиtype()иhandle(Document), по реализации на тип. В Spring удобно внедритьList<DocumentHandler>и в конструкторе собратьMap<DocumentType, DocumentHandler>. Новый тип это новый бин, существующий код не трогается; - ключ как enum, а не строка:
EnumMapи проверка при старте, что для каждого значения есть обработчик, превращают ошибку в рантайме в падение при запуске; - sealed-иерархия и pattern matching:
sealed interface Document permits Invoice, Act, Contractиswitchс паттернами по типам, окончательно вошедший в Java 21. Компилятор проверяет полноту,defaultне нужен, и забытый тип становится ошибкой компиляции. Подходит, когда типов мало и они стабильны, а операций много; - полиморфный метод в самом документе:
document.process(). Годится, если обработка действительно часть поведения документа, а не внешняя интеграция.
Покажите, что понимаете компромисс. Стратегия легко добавляет новые типы, но новую операцию придётся дописать во все обработчики. Sealed-иерархия со switch, наоборот, легко добавляет операции. Выбор зависит от того, что в проекте меняется чаще.
Где спотыкаются
Предлагают фабрику со switch внутри и считают задачу решённой. Условие просто переехало в другой класс.
Строят пять уровней абстракций ради трёх типов документов. Интервьюеру важна соразмерность, а не число паттернов.
Оставляют ветку default с IllegalArgumentException: забытый тип обнаружится только в проде. Enum-ключ с проверкой при старте или sealed-типы ловят это раньше.