diff --git a/docs/tasks/EvenOnlySortStrategy.md b/docs/tasks/EvenOnlySortStrategy.md new file mode 100644 index 0000000..306c38c --- /dev/null +++ b/docs/tasks/EvenOnlySortStrategy.md @@ -0,0 +1,368 @@ +# Техническое задание: `EvenOnlySortStrategy` + +## Задача + +Создать класс `EvenOnlySortStrategy`, реализующий дополнительное задание по сортировке элементов с чётным значением выбранного числового поля. + +Класс должен использовать **паттерн Стратегия**: он не реализует собственный алгоритм сортировки, а делегирует сортировку переданной реализации `SortStrategy`. + +## Контракт + +Класс: + +```java +public class EvenOnlySortStrategy implements SortStrategy +``` + +Должен содержать два конструктора: + +```java +public EvenOnlySortStrategy() +``` + +```java +public EvenOnlySortStrategy(SortStrategy sortStrategy) +``` + +Также реализовать метод: + +```java +public void setSortStrategy(SortStrategy sortStrategy) +``` + +и основной метод интерфейса `SortStrategy`: + +```java +@Override +public void sort( + MyList list, + Comparator comparator +) +``` + +Для определения чётности числового поля использовать: + +```java +ToIntFunction +``` + +Поэтому рекомендуется также передавать функцию получения числового значения через конструктор или отдельный метод настройки. + +Для `Student` в качестве функции использовать: + +```java +Student::getRecordBookNumber +``` + +## Поведение при отсутствии стратегии + +Если `sortStrategy` не задан: + +```java +EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>(); +``` + +то вызов: + +```java +strategy.sort(students, comparator); +``` + +должен завершаться контролируемой ошибкой. + +Рекомендуется выбрасывать: + +```java +IllegalStateException +``` + +с понятным сообщением о том, что стратегия сортировки не задана. + +Не следует использовать `null` как признак успешного выполнения сортировки. + +## Поведение `setSortStrategy` + +Метод: + +```java +setSortStrategy(SortStrategy sortStrategy) +``` + +заменяет текущую стратегию. + +После вызова метода последующая сортировка должна выполняться именно переданной стратегией. + +Передача `null` должна приводить к контролируемой ошибке, например: + +```java +IllegalArgumentException +``` + +## Основная бизнес-логика + +`EvenOnlySortStrategy` **не должен содержать код какого-либо алгоритма сортировки**. + +Запрещено реализовывать внутри класса: + +- Merge Sort; +- Bubble Sort; +- Selection Sort; +- другие алгоритмы сортировки; +- вызовы стандартных методов сортировки Java. + +Класс отвечает только за: + +1. определение элементов, участвующих в специальной сортировке; +2. сохранение исходных позиций нечётных элементов; +3. передачу подходящих элементов переданной `SortStrategy`; +4. восстановление результата на исходные позиции; +5. делегирование самого алгоритма сортировки. + +Таким образом: + +```text +EvenOnlySortStrategy + │ + ├── определяет, какие элементы сортировать + │ + ├── передаёт сортируемые элементы + │ ↓ + │ SortStrategy + │ ↓ + │ MergeSortStrategy + │ QuickSortStrategy + │ ... + │ + └── возвращает результат на исходные позиции +``` + +Один `EvenOnlySortStrategy` должен работать с **любой реализацией `SortStrategy`**. + +## Рекомендуемый алгоритм + +Рекомендуется использовать следующий подход. + +Исходная коллекция: + +```text +[7, 8, 3, 2, 5, 4] +``` + +При выборе `recordBookNumber`: + +```text +нечётные: 7, 3, 5 +чётные: 8, 2, 4 +``` + +1. Пройти исходный `MyList`. +2. С помощью `ToIntFunction` определить чётность каждого элемента. +3. Запомнить позиции элементов с чётным значением. +4. Сформировать отдельный `MyList` только из чётных элементов. +5. Передать эту коллекцию в `sortStrategy.sort(...)`. +6. Полученные отсортированные элементы последовательно вернуть на сохранённые позиции. +7. Элементы с нечётными значениями не изменять. + +Например, переданная стратегия `MergeSortStrategy` сортирует: + +```text +[8, 2, 4] +``` + +в: + +```text +[2, 4, 8] +``` + +После возвращения элементов на исходные позиции: + +```text +[7, 2, 3, 4, 5, 8] +``` + +При этом `EvenOnlySortStrategy` не знает, каким способом были отсортированы `8`, `2`, `4`. + +## Работа с любой `SortStrategy` + +Должно быть возможно использовать: + +```java +EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>( + new MergeSortStrategy<>(), + Student::getRecordBookNumber + ); +``` + +А также после создания заменить стратегию: + +```java +strategy.setSortStrategy(new AnotherSortStrategy<>()); +``` + +После этого специальная сортировка должна использовать новую стратегию без изменения `EvenOnlySortStrategy`. + +## Требования к `ToIntFunction` + +Функция получения числового значения должна передаваться извне. + +Для `Student`: + +```java +Student::getRecordBookNumber +``` + +Стратегия не должна напрямую обращаться к: + +```java +student.getRecordBookNumber() +``` + +или к другим полям `Student`. + +Это позволяет использовать класс с другими типами объектов и другими числовыми полями. + +## Требования к коллекциям + +Работать необходимо с: + +```java +MyList +``` + +Использование `ArrayList`, `LinkedList` и других стандартных коллекций для хранения элементов запрещено. + +Вспомогательная коллекция чётных элементов также должна быть `MyList`. + +## Тесты + +### Переданная стратегия используется + +Передать `MergeSortStrategy`. + +Проверить, что сортировка чётных элементов выполняется переданной стратегией. + +### Замена стратегии + +1. Создать `EvenOnlySortStrategy` с одной реализацией `SortStrategy`. +2. Выполнить сортировку. +3. Вызвать `setSortStrategy(...)`. +4. Выполнить сортировку повторно. +5. Проверить, что используется новая стратегия. + +### Конструктор без стратегии + +Создать: + +```java +new EvenOnlySortStrategy<>(); +``` + +Вызвать `sort()`. + +Проверить выброс `IllegalStateException`. + +### Конструктор со стратегией + +Создать объект с `MergeSortStrategy`. + +Проверить успешное выполнение сортировки. + +### Передача `null` в `setSortStrategy` + +Проверить выброс `IllegalArgumentException`. + +### Все элементы нечётные + +```text +[7, 3, 5, 1] +``` + +Результат должен полностью совпадать с исходной коллекцией. + +### Все элементы чётные + +```text +[8, 2, 6, 4] +``` + +Ожидаемый результат: + +```text +[2, 4, 6, 8] +``` + +### Смешанные значения + +```text +[7, 8, 3, 2, 5, 4] +``` + +Ожидаемый результат: + +```text +[7, 2, 3, 4, 5, 8] +``` + +### Повторяющиеся значения + +Проверить корректность сортировки при наличии одинаковых чётных значений. + +### Один элемент + +Проверить отдельно чётный и нечётный элемент. + +### Пустая коллекция + +Сортировка не должна приводить к ошибке. + +### Проверка сохранения нечётных элементов + +Проверить не только значения, но и то, что объекты с нечётным `recordBookNumber` остались на тех же индексах. + +### Проверка разных реализаций + +Использовать `EvenOnlySortStrategy` с каждой доступной реализацией `SortStrategy`. + +Проверить, что результат специальной сортировки соответствует контракту независимо от конкретного алгоритма. + +### Проверка делегирования + +Создать тестовую реализацию `SortStrategy`, которая фиксирует факт вызова `sort()`. + +Передать её в `EvenOnlySortStrategy`. + +Проверить, что: + +- `sort()` был вызван; +- в стратегию передана коллекция только с чётными элементами; +- сама `EvenOnlySortStrategy` не выполняет сортировку самостоятельно. + +## Результат + +Реализовать: + +```text +EvenOnlySortStrategy.java +``` + +Класс должен зависеть от абстракции: + +```text +SortStrategy +MyList +Comparator +ToIntFunction +``` + +и **не должен содержать реализации конкретного алгоритма сортировки**. + +## Git + +Ветка: + +```text +feature/even-only-sort-strategy +```