docs: add even-only sort strategy task
This commit is contained in:
@@ -0,0 +1,368 @@
|
||||
# Техническое задание: `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
|
||||
```
|
||||
Reference in New Issue
Block a user