369 lines
11 KiB
Markdown
369 lines
11 KiB
Markdown
# Техническое задание: `EvenOnlySortStrategy`
|
||
|
||
## Задача
|
||
|
||
Создать класс `EvenOnlySortStrategy`, реализующий дополнительное задание по сортировке элементов с чётным значением выбранного числового поля.
|
||
|
||
Класс должен использовать **паттерн Стратегия**: он не реализует собственный алгоритм сортировки, а делегирует сортировку переданной реализации `SortStrategy`.
|
||
|
||
## Контракт
|
||
|
||
Класс:
|
||
|
||
```java
|
||
public class EvenOnlySortStrategy<T> implements SortStrategy<T>
|
||
```
|
||
|
||
Должен содержать два конструктора:
|
||
|
||
```java
|
||
public EvenOnlySortStrategy()
|
||
```
|
||
|
||
```java
|
||
public EvenOnlySortStrategy(SortStrategy<T> sortStrategy)
|
||
```
|
||
|
||
Также реализовать метод:
|
||
|
||
```java
|
||
public void setSortStrategy(SortStrategy<T> sortStrategy)
|
||
```
|
||
|
||
и основной метод интерфейса `SortStrategy`:
|
||
|
||
```java
|
||
@Override
|
||
public void sort(
|
||
MyList<T> list,
|
||
Comparator<T> comparator
|
||
)
|
||
```
|
||
|
||
Для определения чётности числового поля использовать:
|
||
|
||
```java
|
||
ToIntFunction<T>
|
||
```
|
||
|
||
Поэтому рекомендуется также передавать функцию получения числового значения через конструктор или отдельный метод настройки.
|
||
|
||
Для `Student` в качестве функции использовать:
|
||
|
||
```java
|
||
Student::getRecordBookNumber
|
||
```
|
||
|
||
## Поведение при отсутствии стратегии
|
||
|
||
Если `sortStrategy` не задан:
|
||
|
||
```java
|
||
EvenOnlySortStrategy<Student> strategy =
|
||
new EvenOnlySortStrategy<>();
|
||
```
|
||
|
||
то вызов:
|
||
|
||
```java
|
||
strategy.sort(students, comparator);
|
||
```
|
||
|
||
должен завершаться контролируемой ошибкой.
|
||
|
||
Рекомендуется выбрасывать:
|
||
|
||
```java
|
||
IllegalStateException
|
||
```
|
||
|
||
с понятным сообщением о том, что стратегия сортировки не задана.
|
||
|
||
Не следует использовать `null` как признак успешного выполнения сортировки.
|
||
|
||
## Поведение `setSortStrategy`
|
||
|
||
Метод:
|
||
|
||
```java
|
||
setSortStrategy(SortStrategy<T> 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<T>` определить чётность каждого элемента.
|
||
3. Запомнить позиции элементов с чётным значением.
|
||
4. Сформировать отдельный `MyList<T>` только из чётных элементов.
|
||
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<Student> strategy =
|
||
new EvenOnlySortStrategy<>(
|
||
new MergeSortStrategy<>(),
|
||
Student::getRecordBookNumber
|
||
);
|
||
```
|
||
|
||
А также после создания заменить стратегию:
|
||
|
||
```java
|
||
strategy.setSortStrategy(new AnotherSortStrategy<>());
|
||
```
|
||
|
||
После этого специальная сортировка должна использовать новую стратегию без изменения `EvenOnlySortStrategy`.
|
||
|
||
## Требования к `ToIntFunction`
|
||
|
||
Функция получения числового значения должна передаваться извне.
|
||
|
||
Для `Student`:
|
||
|
||
```java
|
||
Student::getRecordBookNumber
|
||
```
|
||
|
||
Стратегия не должна напрямую обращаться к:
|
||
|
||
```java
|
||
student.getRecordBookNumber()
|
||
```
|
||
|
||
или к другим полям `Student`.
|
||
|
||
Это позволяет использовать класс с другими типами объектов и другими числовыми полями.
|
||
|
||
## Требования к коллекциям
|
||
|
||
Работать необходимо с:
|
||
|
||
```java
|
||
MyList<T>
|
||
```
|
||
|
||
Использование `ArrayList`, `LinkedList` и других стандартных коллекций для хранения элементов запрещено.
|
||
|
||
Вспомогательная коллекция чётных элементов также должна быть `MyList<T>`.
|
||
|
||
## Тесты
|
||
|
||
### Переданная стратегия используется
|
||
|
||
Передать `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<T>
|
||
MyList<T>
|
||
Comparator<T>
|
||
ToIntFunction<T>
|
||
```
|
||
|
||
и **не должен содержать реализации конкретного алгоритма сортировки**.
|
||
|
||
## Git
|
||
|
||
Ветка:
|
||
|
||
```text
|
||
feature/even-only-sort-strategy
|
||
```
|