Чем можно заменить if java

альтернатива оператору if в java

так что, как вы видите, все операторы if являются отдельными, а не другими условиями. Обратите внимание, что XYZ — это совершенно разные условия, поэтому переключатель не подходит.

Хотя любопытство может быть забавным . зачем мне альтернатива if, особенно когда условие состоит в том, что переключатель не подходит? Как будто Java еще недостаточно раздулась. — ty812

либо то, что вы пытаетесь сделать, глупо (если это здорово!), либо вам нужно предоставить больше информации. Я могу представить себе ситуацию, когда подобный код можно было бы обработать с помощью шаблона обмена сообщениями или чего-то еще интересного (при условии, что ваша ситуация не так проста, как вы ее объяснили). — twolfe18

Что вы ожидаете от этой альтернативы, чего не может предоставить представленный код? (меньше символов, больше читаемости?) — Zed

@Hellnar: Есть дополнительные знания, которые имеют ценность, и есть неясный код для гольфа. — S.Lott

11 ответы

Одним из «истинно объектно-ориентированных» ответов было бы определить интерфейс для «Правила» (с методами condition() и action()), создать 3 реализации, поместить их в коллекцию, а затем просто выполнить итерацию по ним в общем, как в:

Список правила = . ; // ваши 3 правила каким-то образом инициализированы здесь for(Rule r : rules) < if(r.condition()) < r.action(); >>

Это имеет гораздо больше смысла, если у вас есть 300 правил/условий, а не только 3. В Java8 вы можете сделать это вместо этого, если правила интенсивно используют ЦП:

rules.parallelStream().filter(Rule::condition).forEach(Rule::action); 

Карта здесь не сработает, потому что условие уникально для каждой реализации правила. Map требует фактического ключа, а не какого-то кода, скрытого в вызываемом методе. — Alex R

  1. Полиморфизм, когда поведение зависит от начальных значений
  2. Ссылочное присвоение, когда вы знаете возможные начальные значения, и они имеют корреляцию 1 к 1 с возвращаемыми значениями. Списки для этого лучше, чем массивы, но.
// Example: if (a==1) < b=2; >if (a==2) < b=17; >// Becomes int fx(2); // our array of answers fx[0] = 2; fx[1] = 17; b = fx[ a - 1 ]; 
// Example: if (a==1) < doSomething1(); >if (a==2) < doSomething2(); >// Becomes function * fx(2); // our array or better still, list of functions fx[0] = &doSomething1; fx[1] = &doSomething2; `fx[ a - 1 ](); ` 
if (thisCondition == true) < b = true; >else

Альтернативы if-else в Java — оператор switch и оператор условно троичный (?:), ни один из которых не делает именно то, что вы просите (обрабатывает только if без else ). Код, который вы разместили, — лучший способ сделать это, на мой взгляд.

interface SomethingDoer < public void doSomething(); >class ADoer implements SomethingDoer < . >class BDoer implements SomethingDoer < . >class CDoer implements SomethingDoer < . >public class Main < public static void main (String[] args) < SomethingDoer doer = new SomethingDoerFactory(args).getDoer(); doer.doSomething(); >> 

Оператор if не устранен полностью, но перемещен в SomethingDoerFactory. Это решение применимо не во всех случаях, но в некоторых из них является очень хорошей альтернативой множественным «если».

Читайте также:  Fonts with html codes

Любые комментарии о том, почему вы минусуете? Разве это не альтернатива? Или это недостаточно хорошо, чтобы быть упомянутым? — Артемб

Я бы рассматривал полиморфное решение только в том случае, если бы мое условное выражение уже было основано на напишите. Я бы не стал создавать целую иерархию классов только для того, чтобы заменить if(x) do a; — Билл Ящерица

во многих случаях это имеет смысл. видеть youtube.com/watch?v=4F72VULWFvc — говорит технический специалист Google. (Разговоры о чистом коде — наследование, полиморфизм и тестирование) я считаю, что отрицательный голос неправильный. — Андреас Петерссон

Прямо со слайдов Мисько: «иногда if — это просто if «. Если вы не будете повторно использовать эти операторы if во многих местах, это сделает вещи излишне сложными. Также: ваше решение неполное. Что, если выполняются оба условия x и y? Вы пропустили AAndBDoer, AAndCDoer, BAndCDoer, AAndBAndCDoer; они хорошо покрыты исходным кодом. — Зак Томпсон

Очевидно, это зависит от того, что именно означает «делать». Полиморфизм вполне может быть отличным решением, но пример слишком общий, чтобы иметь единственное решение для всех случаев. AAndBDoer и т. д. обычно решаются с помощью шаблонов Decorator/Composition для решения типа полиморфизма. — Eek

это самое простое, читабельно, но эффективно решение. Я был бы удивлен, увидев здесь эффективные альтернативы.

можно попробовать применить метод извлечения несколько раз:

Я делаю это в прошивке для устройства, в котором может быть включено или отключено множество различных опций. Я бы предпочел, чтобы мой main() вызывал такие вещи, как doFooIfEnabled(), чем загромождал его множеством ifs и #ifdefs. — Жанна Пиндар

Как и любой шаблон, есть моменты, когда его следует использовать, и моменты, когда его не следует использовать. — бдонлан

Сделайте что-то вроде этого: внедрите Enum на основе условия и вызовите метод переопределения.

public enum Rule < a()< @Override public void do()< // do something. >>, b() < @Override public void do()< // do something. >>, c() < @Override public void do()< // do something. >public abstract void do(); > > public class Test < public static void main(String[] args)< Rule r = Rule.valueOf("a"); r.do(); >> 

Источник

Как заменить многие операторы if в Java

Конструкции принятия решений являются жизненно важной частью любого языка программирования. Но мы попадаем в кодирование огромного количества вложенных операторов if, которые делают наш код более сложным и трудным в обслуживании.

В этом уроке мы рассмотрим различные способы замены вложенных операторов if .

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

2. Тематическое исследование

Часто мы сталкиваемся с бизнес-логикой, которая включает в себя множество условий, и каждое из них требует различной обработки. Для демонстрации давайте возьмем пример класса Calculator . У нас будет метод, который принимает два числа и оператор в качестве входных данных и возвращает результат на основе операции:

public int calculate(int a, int b, String operator) < int result = Integer.MIN_VALUE; if ("add".equals(operator)) < result = a + b; >else if ("multiply".equals(operator)) < result = a * b; >else if ("divide".equals(operator)) < result = a / b; >else if ("subtract".equals(operator)) < result = a - b; >return result; >

Мы также можем реализовать это с помощью switch statements :

public int calculateUsingSwitch(int a, int b, String operator) < switch (operator) < case "add": result = a + b; break; // other cases >return result; >

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

Читайте также:  direction

Еще одним побочным эффектом вложенных конструкций решений является то, что они становятся неуправляемыми. Например, если нам нужно добавить новый оператор, мы должны добавить новый оператор if и реализовать операцию.

3. Рефакторинг

Давайте рассмотрим альтернативные варианты замены сложных операторов if выше на гораздо более простой и управляемый код.

3.1. Заводской класс

Много раз мы сталкиваемся с конструкциями решений, которые в конечном итоге выполняют аналогичную операцию в каждой ветви. Это дает возможность извлечь фабричный метод, который возвращает объект заданного типа и выполняет операцию на основе поведения конкретного объекта .

Для нашего примера давайте определим интерфейс Operation , который имеет один apply метод:

public interface Operation

Метод принимает два числа в качестве входных данных и возвращает результат. Давайте определим класс для выполнения дополнений:

public class Addition implements Operation < @Override public int apply(int a, int b) < return a + b; >>

Теперь мы реализуем фабричный класс, который возвращает экземпляры Operation на основе данного оператора:

public class OperatorFactory < static MapoperationMap = new HashMap<>(); static < operationMap.put("add", new Addition()); operationMap.put("divide", new Division()); // more operators >public static Optional getOperation(String operator) < return Optional.ofNullable(operationMap.get(operator)); >>

Теперь в классе Calculator мы можем запросить завод, чтобы получить соответствующую операцию и применить исходные номера:

public int calculateUsingFactory(int a, int b, String operator) < Operation targetOperation = OperatorFactory .getOperation(operator) .orElseThrow(() ->new IllegalArgumentException("Invalid Operator")); return targetOperation.apply(a, b); >

В этом примере мы видели, как ответственность делегируется слабо связанным объектам, обслуживаемым фабричным классом. Но могут быть шансы, что вложенные операторы if просто будут перенесены в класс factory, что противоречит нашей цели.

В качестве альтернативы, мы можем поддерживать репозиторий объектов в Карте , который может быть запрошен для быстрого поиска . Как мы видели, Operator Factory#operation Map служит нашей цели. Мы также можем инициализировать Map во время выполнения и настроить их для поиска.

3.2. Использование перечислений

В дополнение к использованию Map, мы также можем использовать Enum для обозначения конкретной бизнес-логики . После этого мы можем использовать их либо во вложенных операторах if , либо в операторах |//switch case |//. Кроме того, мы также можем использовать их в качестве фабрики объектов и разрабатывать стратегию для выполнения соответствующей бизнес-логики.

Это также уменьшило бы количество вложенных операторов if и делегировало бы ответственность отдельным значениям Enum .

Давайте посмотрим, как мы можем этого достичь. Сначала нам нужно определить наше Перечисление :

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

Мы определим методы для каждого из значений Enum и выполним расчет. Например:

ADD < @Override public int apply(int a, int b) < return a + b; >>, // other operators public abstract int apply(int a, int b);

А затем в классе Calculator мы можем определить метод для выполнения операции:

Читайте также:  Php and remote address

public int calculate(int a, int b, Operator operator)

Теперь мы можем вызвать метод путем преобразования String значения в Оператор с помощью Operator#valueOf() метод :

@Test public void whenCalculateUsingEnumOperator_thenReturnCorrectResult()

3.3. Шаблон команд

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

Мы также можем разработать метод калькулятора#calculate , чтобы принять команду, которая может быть выполнена на входах . Это будет еще один способ замены вложенных операторов if .

Сначала мы определим наш Командный интерфейс:

Далее, давайте реализуем команду Add:

public class AddCommand implements Command < // Instance variables public AddCommand(int a, int b) < this.a = a; this.b = b; >@Override public Integer execute() < return a + b; >>

Наконец, давайте представим новый метод в Калькуляторе , который принимает и выполняет команду :

public int calculate(Command command)

Затем мы можем вызвать вычисление, создав экземпляр команды Add и отправив ее в метод Calculator#calculate :

@Test public void whenCalculateUsingCommand_thenReturnCorrectResult()

3.4. Механизм правил

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

Давайте рассмотрим пример, разработав простой механизм Правил , который обрабатывает Выражение через набор Правил и возвращает результат из выбранного Правила . Во-первых, мы определим Правило интерфейс:

Во-вторых, давайте реализуем Механизм правил :

public class RuleEngine < private static Listrules = new ArrayList<>(); static < rules.add(new AddRule()); >public Result process(Expression expression) < Rule rule = rules .stream() .filter(r ->r.evaluate(expression)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Expression does not matches any Rule")); return rule.getResult(); > >

Механизм Правил принимает Выражение объекта и возвращает Результат . Теперь , давайте спроектируем класс Expression как группу из двух Целых объектов с оператором , который будет применен:

И, наконец, давайте определим пользовательский класс addRule , который вычисляется только тогда, когда указана операция ADD :

public class AddRule implements Rule < @Override public boolean evaluate(Expression expression) < boolean evalResult = false; if (expression.getOperator() == Operator.ADD) < this.result = expression.getX() + expression.getY(); evalResult = true; >return evalResult; > >

Теперь мы вызовем механизм правил с выражением |:

@Test public void whenNumbersGivenToRuleEngine_thenReturnCorrectResult()

4. Заключение

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

Как всегда, мы можем найти полный исходный код в репозитории GitHub .

Читайте ещё по теме:

Источник

Оцените статью