Skip to content

Commit 85d9ab5

Browse files
author
Никита
committed
- Реализовал стратегии рандомного RandomDataGeneratorStrategy ввода и ручного ManualInputReaderStrategy ввода
- Реализовал InputManager как Context в паттерне Strategy - Добавил фабричные методы для создания стратегий - Внедрил единую точку входа для всех типов ввода - Добавил валидацию параметров и обработку ошибок
1 parent 512dfa5 commit 85d9ab5

9 files changed

Lines changed: 542 additions & 29 deletions

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies {
1313
testImplementation platform('org.junit:junit-bom:5.10.0')
1414
testImplementation 'org.junit.jupiter:junit-jupiter'
1515
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
16+
implementation 'com.github.javafaker:javafaker:1.0.2'
1617
}
1718

1819
test {

src/main/java/input/CustomCollection.java

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,28 @@
1313
*
1414
* <p>Реализует интерфейс {@link Iterable} для поддержки for-each циклов и стримов.
1515
*
16+
* <p>Основные возможности:</p>
17+
* <ul>
18+
* <li>Динамическое расширение при добавлении элементов</li>
19+
* <li>Поддержка операций добавления, удаления, получения и замены элементов</li>
20+
* <li>Итерация через for-each циклы и итераторы</li>
21+
* <li>Поддержка Stream API</li>
22+
* <li>Добавление всех элементов из другой коллекции</li>
23+
* </ul>
24+
*
1625
* @param <T> тип элементов, хранимых в коллекции
1726
*/
1827
public class CustomCollection<T> implements Iterable<T> {
28+
/** Коэффициент увеличения емкости при расширении массива. */
1929
private static final float GROWTH_FACTOR = 1.5f;
30+
31+
/** Начальная емкость по умолчанию при создании коллекции без указания размера. */
2032
private static final int DEFAULT_CAPACITY = 10;
2133

34+
/** Внутренний массив для хранения элементов коллекции. */
2235
private Object[] elements;
36+
37+
/** Количество фактически хранящихся элементов в коллекции. */
2338
private int size;
2439

2540
public CustomCollection() {
@@ -33,8 +48,6 @@ public CustomCollection(int initialCapacity) {
3348
this.elements = new Object[initialCapacity];
3449
}
3550

36-
// TODO Конструктор из существующей коллекции, копирует все элементы с ёмкостью равной ёмкости коллекции
37-
3851
public boolean add(T element) {
3952
// Проверяем достаточно ли места для добавления
4053
if (size == elements.length) {
@@ -77,14 +90,14 @@ public void clear() {
7790

7891
public T get(int index) {
7992
if (index < 0 || index >= size) {
80-
throw new IndexOutOfBoundsException("Index cannot be less then 0 or more then " + size);
93+
throw new IndexOutOfBoundsException("Индекс не может быть меньше 0 или больше " + size);
8194
}
8295
return (T) elements[index];
8396
}
8497

8598
public T set(int index, T element) {
8699
if (index < 0 || index >= size) {
87-
throw new IndexOutOfBoundsException("Index cannot be less then 0 or more then " + size);
100+
throw new IndexOutOfBoundsException("Индекс не может быть меньше 0 или больше " + size);
88101
}
89102

90103
T old = (T) elements[index];
@@ -109,6 +122,9 @@ public Stream<T> stream() {
109122
* <p>Порядок элементов в целевой коллекции соответствует порядку,
110123
* в котором они возвращаются итератором указанной коллекции.
111124
*
125+
* <p>Поведение этого метода не определено, если указанная коллекция изменяется
126+
* в процессе выполнения операции.
127+
*
112128
* @param collection коллекция, содержащая элементы для добавления
113129
* @return {@code true} если эта коллекция изменилась в результате вызова
114130
*/
@@ -145,18 +161,37 @@ public Iterator iterator() {
145161
return new CustomArrayIterator();
146162
}
147163

148-
// Внутренний клас для итератора
164+
/**
165+
* Внутренний класс итератора для CustomCollection.
166+
* Реализует fail-fast поведение: выбрасывает {@link IllegalStateException}
167+
* при попытке удаления без предварительного вызова {@link #next()}.
168+
*/
149169
class CustomArrayIterator implements Iterator<T> {
150-
private int cursor = 0; // текущая позиция
151-
private int lastRet = -1; // индекс последнего возвращенного элемента
170+
/** Текущая позиция итератора в массиве элементов. */
171+
private int cursor = 0;
172+
173+
/** Индекс последнего возвращенного элемента; -1 если элемент не был возвращен или был удален. */
174+
private int lastRet = -1;
152175

153176
public CustomArrayIterator() {
154177
}
155178

179+
/**
180+
* Проверяет, существует ли следующий элемент для итерации.
181+
*
182+
* @return {@code true} если итерация содержит больше элементов,
183+
* {@code false} в противном случае
184+
*/
156185
public boolean hasNext() {
157186
return cursor < size;
158187
}
159188

189+
/**
190+
* Возвращает следующий элемент в итерации.
191+
*
192+
* @return следующий элемент в итерации
193+
* @throws NoSuchElementException если итерация не содержит больше элементов
194+
*/
160195
public T next() {
161196
if (!hasNext()) {
162197
throw new NoSuchElementException("Элемент отсутствует");
@@ -168,6 +203,12 @@ public T next() {
168203
return element;
169204
}
170205

206+
/**
207+
* Удаляет из коллекции последний элемент, возвращенный этим итератором.
208+
*
209+
* @throws IllegalStateException если метод {@link #next} еще не был вызван,
210+
* или метод {@link #remove} уже был вызван после последнего вызова {@link #next}
211+
*/
171212
public void remove() {
172213
if (lastRet == -1) {
173214
throw new IllegalStateException();
Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,109 @@
11
package input;
22

3+
import input.Strategy.*;
4+
import dto.Client;
5+
6+
import java.io.IOException;
7+
8+
/**
9+
* Менеджер ввода данных, реализующий паттерн Strategy.
10+
* Выступает в роли Context для управления различными стратегиями ввода данных о клиентах.
11+
*
12+
* <p>Основные функции:</p>
13+
* <ul>
14+
* <li>Управление текущей стратегией ввода</li>
15+
* <li>Загрузка данных с использованием выбранной стратегии</li>
16+
* <li>Создание стратегий различных типов</li>
17+
* </ul>
18+
*
19+
* @see ClientInputStrategy
20+
* @see FileReaderStrategy
21+
* @see ManualInputReaderStrategy
22+
* @see RandomDataGeneratorStrategy
23+
* @see CustomCollection
24+
* @see Client
25+
*/
326
public class InputManager {
4-
CustomCollection customCollection = new CustomCollection();
5-
}
27+
private ClientInputStrategy currentStrategy;
28+
29+
30+
public InputManager() {
31+
// Инициализация без стратегии
32+
}
33+
34+
public InputManager(ClientInputStrategy initialStrategy) {
35+
if (initialStrategy == null) {
36+
throw new IllegalArgumentException("Стратегия не может быть null");
37+
}
38+
this.currentStrategy = initialStrategy;
39+
}
40+
41+
public void setStrategy(ClientInputStrategy strategy) {
42+
if (strategy == null) {
43+
throw new IllegalArgumentException("Стратегия не может быть null");
44+
}
45+
this.currentStrategy = strategy;
46+
}
47+
48+
public ClientInputStrategy getCurrentStrategy() {
49+
return currentStrategy;
50+
}
51+
52+
/**
53+
* Загружает данные о клиентах с использованием текущей стратегии.
54+
*
55+
* @return коллекция клиентов, загруженных с помощью текущей стратегии
56+
* @throws IllegalStateException если стратегия не установлена
57+
* @throws IOException если возникает ошибка ввода-вывода при загрузке данных
58+
*/
59+
public CustomCollection<Client> loadData() throws IOException {
60+
if (currentStrategy == null) {
61+
throw new IllegalStateException("Стратегия ввода не установлена. " +
62+
"Используйте setStrategy() перед вызовом loadData()");
63+
}
64+
return currentStrategy.getData();
65+
}
66+
67+
/**
68+
* Создает стратегию для чтения данных из файла.
69+
*
70+
* <p>Файл должен содержать данные в формате:</p>
71+
* <pre>
72+
* Имя|Телефон|ID
73+
* Иван Иванов|+79991234567|1
74+
* </pre>
75+
*
76+
* @param filePath путь к файлу с данными о клиентах
77+
* @return стратегия чтения из файла
78+
* @throws IllegalArgumentException если {@code filePath} равен {@code null} или пуст
79+
*/
80+
public FileReaderStrategy createFileStrategy(String filePath) {
81+
if (filePath == null || filePath.trim().isEmpty()) {
82+
throw new IllegalArgumentException("Путь к файлу не может быть null или пустым");
83+
}
84+
return new FileReaderStrategy(filePath);
85+
}
86+
87+
/**
88+
* Создает стратегию для ручного ввода данных через консоль.
89+
*
90+
* <p>Стратегия предоставляет интерактивный интерфейс для ввода данных
91+
* о клиентах с валидацией и подтверждением.</p>
92+
*
93+
* @return стратегия ручного ввода
94+
*/
95+
public ManualInputReaderStrategy createManualStrategy() {
96+
return new ManualInputReaderStrategy();
97+
}
98+
99+
/**
100+
* Создает стратегию для генерации случайных данных о клиентах.
101+
*
102+
* @param count количество клиентов для генерации
103+
* @return стратегия генерации случайных данных
104+
* @throws IllegalArgumentException если {@code count} меньше или равен 0
105+
*/
106+
public RandomDataGeneratorStrategy createRandomStrategy(int count) {
107+
return new RandomDataGeneratorStrategy(count);
108+
}
109+
}

src/main/java/input/Strategy/FileReader.java renamed to src/main/java/input/Strategy/FileReaderStrategy.java

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import dto.Client;
44
import input.CustomCollection;
55

6-
import java.io.File;
76
import java.io.IOException;
87
import java.nio.charset.StandardCharsets;
98
import java.nio.file.Files;
@@ -13,13 +12,46 @@
1312
import java.util.stream.Stream;
1413

1514
/**
16-
* Стратегия для чтения данных о клиентах из файла.
17-
* Реализует интерфейс ClientInputStrategy для получения коллекции клиентов.
15+
* Стратегия для чтения данных о клиентах из текстового файла.
16+
* Реализует интерфейс {@link ClientInputStrategy} для получения
17+
* коллекции клиентов из внешнего файла.
18+
*
19+
* <p>Формат файла:</p>
20+
* <ul>
21+
* <li>Каждая строка представляет одного клиента</li>
22+
* <li>Формат строки: {@code Имя|Телефон|ID}</li>
23+
* <li>Разделитель полей: вертикальная черта ({@code |})</li>
24+
* <li>Кодировка файла: UTF-8</li>
25+
* </ul>
26+
*
27+
* <p>Требования к данным:</p>
28+
* <ul>
29+
* <li>Имя: непустая строка</li>
30+
* <li>Телефон: формат {@code +7XXXXXXXXXX} (11 цифр после {@code +7})</li>
31+
* <li>ID: целое число</li>
32+
* </ul>
33+
*
34+
* <p>Обработка ошибок:</p>
35+
* <ul>
36+
* <li>Пропускает некорректные строки с выводом сообщения об ошибке</li>
37+
* <li>Игнорирует пустые строки</li>
38+
* <li>Генерирует исключение при проблемах с файлом</li>
39+
* </ul>
40+
*
41+
* <p>Пример содержимого файла:</p>
42+
* <pre>
43+
* Иван Иванов|+79991234567|1
44+
* Мария Петрова|+79997654321|2
45+
* </pre>
46+
*
47+
* @see ClientInputStrategy
48+
* @see Client
49+
* @see CustomCollection
1850
*/
19-
public class FileReader implements ClientInputStrategy {
51+
public class FileReaderStrategy implements ClientInputStrategy {
2052
private final String filePath;
2153

22-
public FileReader(String filePath) {
54+
public FileReaderStrategy(String filePath) {
2355
this.filePath = filePath;
2456
}
2557

@@ -37,7 +69,7 @@ public CustomCollection<Client> getData() {
3769
Path path = Paths.get(filePath);
3870

3971
if (!Files.exists(path)) {
40-
throw new RuntimeException("File not found: " + filePath);
72+
throw new RuntimeException("Файл не найден: " + filePath);
4173
}
4274

4375
try (Stream<String> lines = Files.lines(path, StandardCharsets.UTF_8)) {
@@ -67,7 +99,7 @@ public Optional<Client.ClientBuilder> parseToClient(String line) {
6799
try {
68100
String[] parts = line.split("\\|");
69101
if (parts.length != 3) {
70-
throw new IllegalArgumentException("Invalid data format");
102+
throw new IllegalArgumentException("неверный формат данных");
71103
}
72104
String name = parts[0].trim();
73105
String phoneNumber = parts[1].trim();
@@ -76,17 +108,17 @@ public Optional<Client.ClientBuilder> parseToClient(String line) {
76108
try {
77109
idNumber = Integer.parseInt(parts[2].trim());
78110
} catch (NumberFormatException e) {
79-
System.out.println("[WARN] Missing line (ID is not a number): " + line);
111+
System.out.println("ID не число: " + line);
80112
return Optional.empty();
81113
}
82114

83115
if (name.isEmpty()) {
84-
System.out.println("[WARN] Missing line (name is empty): " + line);
116+
System.out.println("Пустое имя" + line);
85117
return Optional.empty();
86118
}
87119

88120
if (!phoneNumber.matches("^\\+7\\d{10}$")) {
89-
System.out.println("[WARN] Missing line (invalid phone format): " + line);
121+
System.out.println("Неверный формат номера телефона" + line);
90122
return Optional.empty();
91123
}
92124

@@ -97,7 +129,7 @@ public Optional<Client.ClientBuilder> parseToClient(String line) {
97129
return Optional.of(builder);
98130

99131
} catch (Exception e) {
100-
System.out.println("[ERROR] Error processing line: " + line);
132+
System.out.println("Ошибка" + line);
101133
return Optional.empty();
102134
}
103135
}

src/main/java/input/Strategy/ManualInputReader.java

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)