Конструкция
for...each
не является подходящим инструментом для получения определенного поведения, которое вы задаете после формулировки вопроса, без дополнительных функций в объекте Cat
. Классический Iterator
предназначен для обеспечения именно этого типа функциональности. Я думаю, что вопрос показывает, что дизайн имеет недостатки, подробнее об этом.
Предполагается, что существует отсортированный список кошек с именем cats
. List
, который не гарантирует порядок обхода, не будет хорошим кандидатом для итерации, независимо от того, как обходится список.
final Iterator<Cat> iterator = cats.iterator();
while (iterator.hasNext())
{
final Cat cat = iterator.next();
this.feedDryCatFood(cat);
// special case, if there are no more cats in the list
// feed the last one tuna as well.
if (!iterator.hasNext())
{
this.alsoFeedTuna(cat);
}
}
лучшим решением было бы использование метода-члена в Cat
. Cat.isSpecial()
, который возвращает boolean
. Это было бы более самодокументированным и вывело бы поведение из конструкции цикла. Тогда вы могли бы использовать конструкцию for...each
с простым тестом, который самодостаточен и самодокументирован.
if (cat.isSpecial())
{
this.feedTuna(cat);
}
Я думаю, что "последний элемент петли for..each
" в вопросе - красная сельдь. Я думаю, что проблема в большей степени является проблемой проектирования, чем проблемой бизнес-логики, и тот факт, что цикл for...each
не может вместить правило, указывает на необходимость рефакторинга.
Этот новый дизайн также может вместить несколько «специальных» кошек без каких-либо сложностей с кодом.
Другими более элегантными объектно-ориентированными решениями будут Шаблон посетителя или Шаблон цепочки ответственности . Шаблон посетителя абстрагирует логику того, кто какой фаворит из Cat
, и в реализацию посетителя. То же самое с Цепью Ответственности. Имейте цепочку из CatFeeder
объектов, и пусть они решают, «обработать» ли кормление или передать его по цепочке. В любом случае было бы более слабое сцепление и более плотное сцепление.