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