Чем заменить switch java
Перейти к содержимому

Чем заменить switch java

  • автор:

Чем можно заменить switch/case в данном коде?

Условных операторов в C/C++ два — switch() и if() else . Т.е. вместо свитча можно написать многоэтажную конструкцию из ифов. Но вообще как раз switch() сделан чтобы заменить нечитаемые многоэтажные конструкции из if()

23 ноя 2022 в 14:37
@DmitryK, конкретно тут можно заменить на один if внутри for . Но придётся и ещё кое что изменить.
23 ноя 2022 в 14:45

@ГерманБорисов я писал для общего случая. А так — да, согласен, конкретно в этом коде можно заменить на один if()

23 ноя 2022 в 14:50

Кстати, у вас тут 2 возможных ошибки. 1 — при columns==1 , будет вечный цикл while(c2 == c1) < c2 = rand() % columns; >2 — columns==2 , будет деление на ноль l = c[rand()%(columns-2)];

23 ноя 2022 в 15:01

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Код внутри свитча отличается только счётчиками операций, связанных индивидуально с каждой. Можно создать структуру из имени операции и счётчика. Потом случайно выбираете адрес этой структуры и выполняете идентичные действия, не зависящие с именем операции.

В вашем коде доступ к массиву l = c[rand()%(columns-2)]; очень опасный. Вы уверены, что размер массива c больше или равен columns-2 ?

#include typedef struct s_char_int t_char_int ; struct s_char_int < char c ; int n ; >; void generator(const int rows, const int columns, char field[rows][columns])< t_char_int cn[] = ,,, ,,,,, >; char l ; int c1 = rand() % columns; int c2 = rand() % columns; while(c2 == c1) < c2 = rand() % columns; >for (int i = 0; i < columns; i++) < if (i == c1 || i == c2) < for (int y = 0; y < rows; y++) < field[y][i] = ' '; >continue; > for (int y = 0; y < rows; y++) < t_char_int * r = & cn[rand()%(columns-2)] ; l = r->c; if ( l != ' ' ) < if ( r->n < rows) < field[y][i] = l; r->n++; > else < y--; >> > > > 

Замена if на switch

Author24 — интернет-сервис помощи студентам

Замена if else на switch
Доброго времени суток. Нуждаюсь в помощи с лабораторной работой. Задание: написать программу.

Замена конструкции switch словарем
Здравствуйте форумчане! Есть задача вывести словами трехзначное число(325 -> ТристаДвадцатьПять.

Замена if на switch
Задача. Это нужно сделать с помощью switch. ( Для натурального числа k вывести фразу “Мы нашли k.

Замена switch на if
Задание: Заменить в примере оператор switch структурой операторов if. Вопрос: Как можно заменить.

Эксперт Java

3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220

switch можно использовать, когда одна переменная может принимать много значений. У тебя разные переменные и дублирующийся код.

Регистрация: 27.09.2013
Сообщений: 43

Не тот код, вот здесь нужно ifы заменить как-то.
А как тут замену произвести, ведь тут ifы в цикле уже (в цикле do. while)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
do { doPlayerMove(field); if (isWin(field, 'X')) { System.out.println("Congrats. You are winner!"); break; } if (isDraw(field)) { System.out.println("Oh.. It's draw! See you soon."); break; } drawField(field); doAIMove(field); if (isWin(field, 'O')) { System.out.println("Sorry. You are loser!"); break; } if (isDraw(field)) { System.out.println("Oh.. It's draw! See you soon."); break; } drawField(field); } while(true);

Регистрация: 27.09.2013
Сообщений: 43
Пытаюсь эти ифы в отдельный метод вынести, что ли, пишет ошибку:
224 / 182 / 80
Регистрация: 13.04.2014
Сообщений: 678
в Java нужно указывать тип входных параметров
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Замена if-ов на switch case
В общем, было такое задание: Дана строка. Найдите в этой строке второе вхождение буквы f и.

Замена большого Switch
Привет, взглянув чуть-чуть наперед, и осознав что код может стать куда больше, появилась.

Замена switch/case
Здравствуйте, я написал программу, теперь хочу чтобы по вводу в консоль 1 у меня выполнялся вот.

Замена switch полиморфизмом
Здравствуйте. Читаю в данный момент книгу по рефакторингу, решил посмотреть свой старый код и.

Оправдана ли замена If на Switch
Всем привет! Я получаю ответ от сервера: string killer; killer = new.

Замена чисел на символы (switch)
Написать программу замены введенного числа от 0 до 9 соответствующим символом (1=! 2=@ . ) с.

Или воспользуйтесь поиском по форуму:

Замена условного оператора полиморфизмом

У вас есть условный оператор, который, в зависимости от типа или свойств объекта, выполняет различные действия.

Решение

Создайте подклассы, которым соответствуют ветки условного оператора. В них создайте общий метод и переместите в него код из соответствующей ветки условного оператора. Впоследствии замените условный оператор на вызов этого метода. Таким образом, нужная реализация будет выбираться через полиморфизм в зависимости от класса объекта.

class Bird < // . double getSpeed() < switch (type) < case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; case NORWEGIAN_BLUE: return (isNailed) ? 0 : getBaseSpeed(voltage); >throw new RuntimeException("Should be unreachable"); > >
abstract class Bird < // . abstract double getSpeed(); >class European extends Bird < double getSpeed() < return getBaseSpeed(); >> class African extends Bird < double getSpeed() < return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; >> class NorwegianBlue extends Bird < double getSpeed() < return (isNailed) ? 0 : getBaseSpeed(voltage); >> // Somewhere in client code speed = bird.getSpeed();
public class Bird < // . public double GetSpeed() < switch (type) < case EUROPEAN: return GetBaseSpeed(); case AFRICAN: return GetBaseSpeed() - GetLoadFactor() * numberOfCoconuts; case NORWEGIAN_BLUE: return isNailed ? 0 : GetBaseSpeed(voltage); default: throw new Exception("Should be unreachable"); >> >
public abstract class Bird < // . public abstract double GetSpeed(); >class European: Bird < public override double GetSpeed() < return GetBaseSpeed(); >> class African: Bird < public override double GetSpeed() < return GetBaseSpeed() - GetLoadFactor() * numberOfCoconuts; >> class NorwegianBlue: Bird < public override double GetSpeed() < return isNailed ? 0 : GetBaseSpeed(voltage); >> // Somewhere in client code speed = bird.GetSpeed();
class Bird < // . public function getSpeed() < switch ($this->type) < case EUROPEAN: return $this->getBaseSpeed(); case AFRICAN: return $this->getBaseSpeed() - $this->getLoadFactor() * $this->numberOfCoconuts; case NORWEGIAN_BLUE: return ($this->isNailed) ? 0 : $this->getBaseSpeed($this->voltage); > throw new Exception("Should be unreachable"); > // . >
abstract class Bird < // . abstract function getSpeed(); // . >class European extends Bird < public function getSpeed() < return $this->getBaseSpeed(); > > class African extends Bird < public function getSpeed() < return $this->getBaseSpeed() - $this->getLoadFactor() * $this->numberOfCoconuts; > > class NorwegianBlue extends Bird < public function getSpeed() < return ($this->isNailed) ? 0 : $this->getBaseSpeed($this->voltage); > > // Somewhere in Client code. $speed = $bird->getSpeed();
class Bird: # . def getSpeed(self): if self.type == EUROPEAN: return self.getBaseSpeed() elif self.type == AFRICAN: return self.getBaseSpeed() - self.getLoadFactor() * self.numberOfCoconuts elif self.type == NORWEGIAN_BLUE: return 0 if self.isNailed else self.getBaseSpeed(self.voltage) else: raise Exception("Should be unreachable")
class Bird: # . def getSpeed(self): pass class European(Bird): def getSpeed(self): return self.getBaseSpeed() class African(Bird): def getSpeed(self): return self.getBaseSpeed() - self.getLoadFactor() * self.numberOfCoconuts class NorwegianBlue(Bird): def getSpeed(self): return 0 if self.isNailed else self.getBaseSpeed(self.voltage) # Somewhere in client code speed = bird.getSpeed()
class Bird < // . getSpeed(): number < switch (type) < case EUROPEAN: return getBaseSpeed(); case AFRICAN: return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; case NORWEGIAN_BLUE: return (isNailed) ? 0 : getBaseSpeed(voltage); >throw new Error("Should be unreachable"); > >
abstract class Bird < // . abstract getSpeed(): number; >class European extends Bird < getSpeed(): number < return getBaseSpeed(); >> class African extends Bird < getSpeed(): number < return getBaseSpeed() - getLoadFactor() * numberOfCoconuts; >> class NorwegianBlue extends Bird < getSpeed(): number < return (isNailed) ? 0 : getBaseSpeed(voltage); >> // Somewhere in client code let speed = bird.getSpeed();

Причины рефакторинга

Этот рефакторинг может помочь, если у вас в коде есть условные операторы, которые выполняют различную работу, в зависимости от:

  • класса объекта или интерфейса, который он реализует;
  • значения какого-то из полей объекта;
  • результата вызова одного из методов объекта.

При этом если у вас появится новый тип или свойство объекта, нужно будет искать и добавлять код во все схожие условные операторы. Таким образом, польза от данного рефакторинга увеличивается, если условных операторов больше одного, и они разбросаны по всем методам объекта.

Достоинства

  • Этот рефакторинг реализует принцип говори, а не спрашивай: вместо того, чтобы спрашивать объект о его состоянии, а потом выполнять на основании этого какие-то действия, гораздо проще просто сказать ему, что нужно делать, а как это делать он решит сам.
  • Убивает дублирование кода. Вы избавляетесь от множества почти одинаковых условных операторов.
  • Если вам потребуется добавить новый вариант выполнения, все, что придётся сделать, это добавить новый подкласс, не трогая существующий код (принцип открытости/закрытости).

Порядок рефакторинга

Подготовка к рефакторингу

Чтобы выполнить этот рефакторинг, вам следует иметь готовую иерархию классов, в которых будут содержаться альтернативные поведения. Если такой иерархии ещё нет, нужно создать её. В этом могут помочь другие рефакторинги:

  • Замена кодирования типа подклассами. При этом для всех значений какого-то свойства объекта будут созданы свои подклассы. Это хоть и простой, но менее гибкий способ, так как нельзя будет создать подклассы для других свойств объекта.
  • Замена кодирования типа состоянием/стратегией. При этом для определенного свойства объекта будет выделен свой класс и из него созданы подклассы для каждого значения этого свойства. Текущий класс будет содержать ссылки на объекты такого типа и делегировать им выполнение.

Последующие шаги этого рефакторинга подразумевают, что вы уже создали иерархию.

Шаги рефакторинга
  1. Если условный оператор находится в методе, который выполняет ещё какие-то действия, извлеките его в новый метод.
  2. Для каждого подкласса иерархии, переопределите метод, содержащий условный оператор, и скопируйте туда код соответствующей ветки оператора.
  3. Удалите эту ветку из условного оператора.
  4. Повторяйте замену, пока условный оператор не опустеет. Затем удалите условный оператор и объявите метод абстрактным.

Устали читать?

Сбегайте за подушкой, у нас тут контента на 7 часов чтения.

Или попробуйте наш интерактивный курс. Он гораздо более интересный, чем банальный текст.

Скидки!

Этот рефакторинг — малая часть интерактивного онлайн курса по рефакторингу.

Refactoring.Guru

  • Премиум контент
    • Книга о паттернах
    • Курс по рефакторингу
    • Введение в рефакторинг
      • Чистый код
      • Технический долг
      • Когда рефакторить
      • Как рефакторить
      • Раздувальщики
        • Длинный метод
        • Большой класс
        • Одержимость элементарными типами
        • Длинный список параметров
        • Группы данных
        • Операторы switch
        • Временное поле
        • Отказ от наследства
        • Альтернативные классы с разными интерфейсами
        • Расходящиеся модификации
        • Стрельба дробью
        • Параллельные иерархии наследования
        • Комментарии
        • Дублирование кода
        • Ленивый класс
        • Класс данных
        • Мёртвый код
        • Теоретическая общность
        • Завистливые функции
        • Неуместная близость
        • Цепочка вызовов
        • Посредник
        • Неполнота библиотечного класса
        • Составление методов
          • Извлечение метода
          • Встраивание метода
          • Извлечение переменной
          • Встраивание переменной
          • Замена переменной вызовом метода
          • Расщепление переменной
          • Удаление присваиваний параметрам
          • Замена метода объектом методов
          • Замена алгоритма
          • Перемещение метода
          • Перемещение поля
          • Извлечение класса
          • Встраивание класса
          • Сокрытие делегирования
          • Удаление посредника
          • Введение внешнего метода
          • Введение локального расширения
          • Самоинкапсуляция поля
          • Замена простого поля объектом
          • Замена значения ссылкой
          • Замена ссылки значением
          • Замена поля-массива объектом
          • Дублирование видимых данных
          • Замена однонаправленной связи двунаправленной
          • Замена двунаправленной связи однонаправленной
          • Замена магического числа символьной константой
          • Инкапсуляция поля
          • Инкапсуляция коллекции
          • Замена кодирования типа классом
          • Замена кодирования типа подклассами
          • Замена кодирования типа состоянием/стратегией
          • Замена подкласса полями
          • Разбиение условного оператора
          • Объединение условных операторов
          • Объединение дублирующихся фрагментов в условных операторах
          • Удаление управляющего флага
          • Замена вложенных условных операторов граничным оператором
          • Замена условного оператора полиморфизмом
          • Введение Null-объекта
          • Введение проверки утверждения
          • Переименование метода
          • Добавление параметра
          • Удаление параметра
          • Разделение запроса и модификатора
          • Параметризация метода
          • Замена параметра набором специализированных методов
          • Передача всего объекта
          • Замена параметра вызовом метода
          • Замена параметров объектом
          • Удаление сеттера
          • Сокрытие метода
          • Замена конструктора фабричным методом
          • Замена кода ошибки исключением
          • Замена исключения проверкой условия
          • Подъём поля
          • Подъём метода
          • Подъём тела конструктора
          • Спуск метода
          • Спуск поля
          • Извлечение подкласса
          • Извлечение суперкласса
          • Извлечение интерфейса
          • Свёртывание иерархии
          • Создание шаблонного метода
          • Замена наследования делегированием
          • Замена делегирования наследованием
          • Введение в паттерны
            • Что такое Паттерн?
            • История паттернов
            • Зачем знать паттерны?
            • Критика паттернов
            • Классификация паттернов
            • Фабричный метод
            • Абстрактная фабрика
            • Строитель
            • Прототип
            • Одиночка
            • Адаптер
            • Мост
            • Компоновщик
            • Декоратор
            • Фасад
            • Легковес
            • Заместитель
            • Цепочка обязанностей
            • Команда
            • Итератор
            • Посредник
            • Снимок
            • Наблюдатель
            • Состояние
            • Стратегия
            • Шаблонный метод
            • Посетитель
            • C#
            • C++
            • Go
            • Java
            • PHP
            • Python
            • Ruby
            • Rust
            • Swift
            • TypeScript

            Как красиво избавиться от switch-case посредством перечисления

            Привет, Хабр! Применение switch-case в коде — давняя тема холиваров на форумах на предмет чистоты кода. Лично я склоняюсь к простому мнению: инструмент необходимо использовать по назначению.

            Сегодня хотелось бы рассмотреть несколько простых кейсов, где switch-case является не лучшим выбором и предложить красивое и удобное решение проблемы.

            Итак, непосредственно, кейс: от значения одной переменной зависит значение другой переменной.

            Исходные данные: программа, имитирующая зоопарк. Она содержит несколько животных, представленных в виде перечисления Animal, и пару работников, описанных интерфейсом ZooWorker.

            public enum Animal
            public interface ZooWorker

            Задача: научить работников кормить животных (по сути — реализовать интерфейс ZooWorker). Алгоритм действия очень прост — необходимо определить название корма, которым питается животное, и вывести в консоль сообщение о том, что животное покормлено и чем именно оно покормлено.

            Первый вариант написан на java 11. Он является самым громоздким и выглядит следующим образом:

            public class Java11Worker implements ZooWorker < @Override public void feed(Animal animal) < String foodName; switch (animal) < case OWL: foodName = "Mouse"; break; case HIPPO: foodName = "Grass"; break; case PENGUIN: foodName = "Fish"; break; case MONKEY: foodName = "Banana"; break; default: throw new IllegalArgumentException("Unknown animal!"); >System.out.printf("%s eat: %s%n", animal, foodName); > >

            Данное решение имеет ряд проблем:

            1. В случае добавления животного в перечисление, требуется дописать и вышеуказанный код.
            2. Разработчику никто не напомнит, что это нужно сделать. Т.е., если зоопарк разрастётся до сотен тысяч строк, вполне можно забыть, что при добавлении животного в перечисление необходимо еще и дописать код. В конце концов, это приведет к ошибке (и хорошо, если определено поведение default, в этом случае, по крайней мере, есть возможность быстро определить проблемное место).
            3. При большом количестве животных switch-case сильно разрастётся.
            4. Ну, и известная проблема switch-case в java 11 – бесконечный break, который легко пропустить.

            Существует возможность немного отрефакторить вышеописанный пример и избавиться от проблемы №4 следующим образом:

            public class Java11Worker implements ZooWorker < @Override public void feed(Animal animal) < String foodName = getFoodName(animal); System.out.printf("%s eat: %s%n", animal, foodName); >private String getFoodName(Animal animal) < switch (animal) < case OWL: return "Mouse"; case HIPPO: return "Grass"; case PENGUIN: return "Fish"; case MONKEY: return "Banana"; default: throw new IllegalArgumentException("Unknown animal!"); >> >

            Выглядит лучше, однако, другие проблемы остаются.

            Начиная с java 14 и выше появилась возможность использовать более удобный формат switch-case. Представленное выше решение в новом формате будет выглядеть следующим образом:

            public class Java17Worker implements ZooWorker < @Override public void feed(Animal animal, int animalCount) < String foodName = switch (animal) < case OWL ->"Mouse"; case HIPPO -> "Grass"; case PENGUIN -> "Fish"; case MONKEY -> "Banana"; >; System.out.printf("%s eat: %s%n", animal, foodName); > >

            Помимо избавления от break, решилась проблема №2: если разработчик добавит в перечисление животное, но не определит необходимое поведение в switch-case, код просто не скомпилируется. Уже лучше, однако, третья и первая проблемы все ещё остаются.

            В последнем решении перенесём зависимость переменных непосредственно в перечисление. Для этого немного изменим его:

            public enum Animal < HIPPO("Grass"), PENGUIN("Fish"), MONKEY("Banana"), OWL("Mouse"); @Getter private final String foodName; Animal(String foodName) < this.foodName = foodName; >>

            Теперь можно реализовать работника всего в одну строку:

            public class EasyWorker implements ZooWorker < @Override public void feed(Animal animal) < System.out.printf("%s eat: %s%n", animal, animal.getFoodName()); >>

            В представленном решении, при добавлении элемента в перечисление, нет необходимости дописывать код, и разработчик точно не забудет нигде ничего дописать. К тому же, код не будет превращаться в лапшу при увеличении количества элементов в перечислении.

            Попробуем немного расширить и усложнить наш кейс: теперь от значения одной переменной зависит не только значение другой, но и последующий алгоритм действий.

            Задача остается той же — научить работников кормить животных. Однако, теперь для того, чтобы покормить животное, необходимо не просто определить требуемый корм, но и рассчитать его объем. Для этого изменим интерфейс ZooWorker:

            public interface ZooWorker

            Для большей наглядности представим, что расчёт корма не везде производится простым умножением на коэффициент, а используется некая формула:

            • Для бегемотов: [количество бегемотов^2]
            • Для филинов: [количество филинов * 3]
            • Для пингвинов: [(количество пингвинов ^ 3)/2]
            • Для обезьян: [количество обезьян * 10]

            Ниже представлены решения по уже используемым шаблонам:

            Решение switch-case на java 11

            public class Java11Worker implements ZooWorker < @Override public void feed(Animal animal, int animalCount) < String foodName; int foodQuantity; switch (animal) < case OWL: foodName = "Mouse"; foodQuantity = animalCount * 3; break; case HIPPO: foodName = "Grass"; foodQuantity = (int) Math.pow(animalCount, 2); break; case MONKEY: foodName = "Banana"; foodQuantity = animalCount * 10; break; case PENGUIN: foodName = "Fish"; foodQuantity = (int) (Math.pow(animalCount, 3)/2); break; default: throw new IllegalArgumentException("Unknown animal!"); >System.out.printf("%s eat: %d %s", animal, foodQuantity, foodName); > >

            Немного переработанный код будет выглядеть следующим образом:

            public class Java11Worker implements ZooWorker < @Override public void feed(Animal animal, int animalCount) < String foodName = getFoodName(animal); int foodQuantity = getfoodQuantity(animal, animalCount); System.out.printf("%s eat: %d %s", animal, foodQuantity, foodName); >private String getFoodName(Animal animal) < switch (animal) < case OWL: return "Mouse"; case HIPPO: return "Grass"; case MONKEY: return "Banana"; case PENGUIN: return "Fish"; default: throw new IllegalArgumentException("Unknown animal!"); >> private int getfoodQuantity(Animal animal, int animalCount) < switch (animal) < case OWL: return animalCount * 3; case HIPPO: return (int) Math.pow(animalCount, 2); case MONKEY: return animalCount * 10; case PENGUIN: return (int) (Math.pow(animalCount, 3)/2); default: throw new IllegalArgumentException("Unknown animal!"); >> > 

            Решение switch-case на java 17

            public class Java17Worker implements ZooWorker < @Override public void feed(Animal animal, int animalCount) < String foodName = switch (animal) < case OWL ->"Mouse"; case HIPPO -> "Grass"; case PENGUIN -> "Fish"; case MONKEY -> "Banana"; >; int foodQuantity = switch (animal) < case OWL ->animalCount * 3; case HIPPO -> (int) Math.pow(animalCount, 2); case PENGUIN -> (int) (Math.pow(animalCount, 3) / 2); case MONKEY -> animalCount * 10; >; System.out.printf("%s eat: %d %s", animal, foodQuantity, foodName); > >

            Для решения через enum требуется доработать перечисление:

            public enum Animal < HIPPO("Grass", animalCount ->(int) Math.pow(animalCount, 2)), PENGUIN("Fish", animalCount -> (int) (Math.pow(animalCount, 3) / 2)), MONKEY("Banana", animalCount -> animalCount * 10), OWL("Mouse", animalCount -> animalCount * 3); @Getter private final String foodName; @Getter private final IntFunction foodCalculation; Animal(String foodName, IntFunction foodCalculation) < this.foodName = foodName; this.foodCalculation = foodCalculation; >>

            И, собственно, сам работник:

            public class EasyWorker implements ZooWorker < @Override public void feed(Animal animal, int animalCount) < System.out.printf("%s eat: %d %s", animal, animal.getFoodCalculation().apply(animalCount), animal.getFoodName() ); >>

            Перейдем к заключительному примеру. Предположим, расчёт корма представляет собой сложную логику, которую не получится передать в качестве лямбды.

            В этом случае для каждого животного создадим отдельного сотрудника, который будет кормить только его.

            public class HippoWorker implements ZooWorker < private final String foodName; public HippoWorker(String foodName) < this.foodName = foodName; >@Override public void feed(int animalCount) < //Сложная логика int foodQuantity = (int) Math.pow(animalCount, 2); System.out.printf("Hippo eat: %d %s", foodQuantity, foodName); >>
            public class MonkeyWorker implements ZooWorker < private final String foodName; public MonkeyWorker(String foodName) < this.foodName = foodName; >@Override public void feed(int animalCount) < //Сложная логика int foodQuantity = animalCount * 10; System.out.printf("Monkey eat: %d %s", foodQuantity, foodName); >>
            public class OwlWorker implements ZooWorker < private final String foodName; public OwlWorker(String foodName) < this.foodName = foodName; >@Override public void feed(int animalCount) < //Сложная логика int foodQuantity = animalCount * 3; System.out.printf("Owl eat: %d %s", foodQuantity, foodName); >>
            public class PenguinWorker implements ZooWorker < private final String foodName; public PenguinWorker(String foodName) < this.foodName = foodName; >@Override public void feed(int animalCount) < //Сложная логика int foodQuantity = (int) (Math.pow(animalCount, 3) / 2); System.out.printf("Penguin eat: %d %s", foodQuantity, foodName); >>

            Представим, как решить задачу «покормить всех животных» «в лоб»: например, в вызывающем классе собираем список (множество) всех работников, и получаем возможность по очереди вызвать метод feed у элементов списка. Вышло бы что-то вроде этого:

            public class Feeder < private final ListworkerList; public Feeder(List workerList) < this.workerList = workerList; >public void feedAll(int animalCount) < workerList.forEach(zooWorker ->zooWorker.feed(animalCount)); > >

            Выглядит неплохо, однако, что делать, если потребуется отдельный метод для каждого животного, например, public void feedHippo(int animalCount) , или универсальный public void feedAnimal(Animal animal, int animalCount) ? На данном этапе возникнут проблемы. Решением может быть создание мапы,содержащей всех работников. Но тогда необходимо хранить ключи к ней (или хардкодить). Можно сделать ключом непосредственно значение перечисления, но все равно придется где-то собирать мапу. Другим решением может стать внедрение работников в качестве полей, но их [работников] может быть много, а feedAnimal будет опять работать на громоздком switch-case. И все эти варианты нужно поддерживать, а при добавлении нового животного придется искать по коду, где отрабатывает логика кормления.

            Однако, если изменим перечисление следующим образом:

            public enum Animal < HIPPO(new HippoWorker("Grass")), PENGUIN(new PenguinWorker("Fish")), MONKEY(new MonkeyWorker("Banana")), OWL(new OwlWorker("Mouse")); private final ZooWorker worker; Animal(ZooWorker worker) < this.worker = worker; >public void feed(int animalCount) < worker.feed(animalCount); >> 

            Все становится настолько простым:

            public class Feeder < public void feedAll(int animalCount) < Arrays.stream(Animal.values()) .forEach(animal ->animal.feed(animalCount)); > public void feedHippo(int animalCount) < Animal.HIPPO.feed(animalCount); >public void feedAnimal(Animal animal, int animalCount) < animal.feed(animalCount); >>

            Мы рассмотрели 3 варианта с нарастающей сложностью, где можно красиво применить перечисление вместо switch-case. Предложенные решения задач просты в реализации и более поддерживаемы и расширяемы по сравнению с решением «в лоб» с использованием switch-case.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *