Есть много неправильных в дизайне этого задания.
Использование enum
Тестовый код содержит следующие фрагменты:
MySimpleIt(erator?).PRIME_NUMBERS
MySimpleIt(erator?).ODD_NUMBERS
MySimpleIt(erator?).EVEN_NUMBERS
В одном месте тип MySimpleIt
, в другом - MySimpleIterator
. В любом случае, имя предлагает использовать интерфейс для определения группы констант. ЭТО НЕ ПРАВИЛЬНОЕ ИСПОЛЬЗОВАНИЕ interface
!!!
Было бы гораздо лучше использовать enum
вместо:
enum SequenceType {
PRIME_NUMBERS, ODD_NUMBERS, EVEN_NUMBERS;
}
См .: Effective Java 2nd Edition Элемент 30: Использовать перечисления вместо int
констант.
Рассмотрим несколько реализаций interface
вместо монолита с setType
Похоже, ваш секвенсор должен иметь возможность переключать тип последовательности по прихоти. Это приведет к тому, что этот класс будет огромным BLOB-объектом, который должен знать, как генерировать последовательности каждого типа. Это может хорошо работать только для 3 типов, приведенных здесь, но это определенно плохой дизайн, если позже вы захотите добавить больше типов последовательностей.
Рассмотрим просто наличие разных реализаций одного и того же интерфейса для разных типов последовательностей. Возможно, вы захотите определить AbstractIntegerSequencer
, который определяет базовую функциональность (сброс границ, ответ hasNext()
, iterator()
и т. Д.), Который делегирует abstract protected int generateNext()
для подклассов @Override
. Таким образом, специфика типа генерируемой последовательности красиво инкапсулируется в каждом подклассе.
Вы все еще можете оставить enum SequenceType
для фабричного метода static
, который создает эти разные подклассы, по одному для каждого типа последовательности, но сами эти последовательности, вероятно, не смогут переключать тип по прихоти.
Используйте дженерики
Вместо того, чтобы делать ваш тип implements Iterator
, вы должны сделать его implements Iterator<Integer>
.
С JLS 4.8 Типы сырья (выделение их):
Использование необработанных типов разрешено только в качестве уступки совместимости устаревшего кода. Использование необработанных типов в коде, написанном после введения универсальности в язык программирования Java, настоятельно не рекомендуется. Возможно, что будущие версии языка программирования Java будут запрещать использование необработанных типов .
См. Также Effective Java 2nd Edition Элемент 32: Не используйте необработанный тип в новом коде.
Не путайте Iterator<T>
с Iterable<T>
.
Допустим, у вас есть что-то вроде этого:
IntegerSequencer seq = new PrimeSequencer(0, 10);
for (int i : seq) {
System.out.println(i);
} // prints "2", "3", "5", 7"
for (int i : seq) {
System.out.println(i);
} // what should it print???
Если вы сделаете seq implements Iterable<Integer>, Iterator<Integer>
и @Override Iterator<Integer> iterator()
до return this;
, то второй цикл не будет ничего печатать, так как seq
является его собственным iterator()
, и на этом этапе больше нет hasNext()
для seq
.
Правильная реализация Iterable<Integer>
должна быть способна генерировать столько независимых Iterator<Integer>
, сколько необходимо пользователю, и такая реализация снова будет печатать простые числа между 0
и 10
в приведенном выше коде.
Дальнейшие чтения по стеку