Замена оператора переключения Java - PullRequest
0 голосов
/ 01 марта 2019

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

public static void example(String action, String from, String to){
 switch (action) {
           case ("run"):
                runTo(from,to);
                break;
           case ("walk"):
                walkTo(from,to);
                break;
           case ("hide"):
                hideAt(to);
                break;
            }
 }

edit: мне было любопытно, есть ли лучший способ вместо использования оператора switch, как в приведенном выше сценарии.

Я немного обновил пример, чтобы сделать немного большесмысл.Некоторые вызовы метода не должны использовать все параметры.

Ответы [ 5 ]

0 голосов
/ 01 марта 2019

Для Java 7 и ниже мы можем объявить интерфейс для реализации функции.

для Java 8+ мы можем использовать Функция интерфейс.

Интерфейс:

public interface FunctionExecutor {
    public Object execute(String from,String to);

}

Контекст функции:

public class FunctionContect {
   HashMap<String, FunctionExecutor> context=new HashMap<String, FunctionExecutor>();

    public void register(String name,FunctionExecutor function){
        context.put(name, function);
    }

   public Object call(String name,String from,String to){
      return    context.get(name).execute(from, to);
   }

   public FunctionExecutor get(String name){
      return context.get(name);
   }

  }

Реализации функций:

public class RunFunctionImpl implements FunctionExecutor{

    @Override
    public Object execute(String from, String to) {
       System.out.println("function run");
        return null;
   }

}

// OTHER FUCNTIONS

Регистрация функции:

    FunctionContect contex = new FunctionContect();
    contex.register("run", new RunFunctionImpl());
    contex.register("walk", new WalkFunctionImpl());
    contex.register("hide", new HideFunctionImpl());

Функция вызова

 context.call(action, from, to);

или

 context.get(action).execute(from,to);
0 голосов
/ 01 марта 2019

Один из возможных вариантов избавления от переключателя - использовать хэш-карту функций:

private String stringMethod(final String action, final String source) {

    final Function<String, String> toLowerFunction = String::toLowerCase;
    final Function<String, String> toUpperFunction = String::toUpperCase;

    final HashMap<String, Function<String, String>> stringFunctions = new HashMap<>();
    stringFunctions.put("toLower", toLowerFunction);
    stringFunctions.put("toUpper", toUpperFunction);

    return stringFunctions.get(action).apply(source);
}
0 голосов
/ 01 марта 2019

Замена переключателя вызовами метода определенно не полная ерунда @Stultuske.Обычно вы используете наследование методов, поэтому разные дочерние классы с одним и тем же родительским классом переопределяют общий метод, и вам не нужно проверять тип подкласса.

С другой стороны, ваш случай выглядит как фабричный метод, но параметры немного смешаны.Я бы предложил Map с String для функции конструктора оболочки.Для случая "ccc" вы должны подумать о чем-то другом (например, аргументы по умолчанию), или у вас всегда есть неиспользуемый параметр i.

0 голосов
/ 01 марта 2019

Если у вас есть повтор случаев переключения на одну и ту же переменную, скажем, в методе f, g и h.Тогда вы можете вывернуть вещи наизнанку:

void f(String a) {
    switch (a) {
    case "aaa": ... ; break;
    ...
    }
}

void g(String a) {
    switch (a) {
    case "aaa": ... ; break;
    case "bbb": ... ; break;
    case "ccc": ... ; break;
    ...
    }
}

void h(String a) {
    switch (a) {
    case "aaa": ... ; break;
    ...
    }
}

Может быть обработан объектно-ориентированно как:

class C {
    public f() { }
    public g() { }
    public h() { }
}

class Aaa extends C {
    @Override
    public f() { test3(b,c); } // Or even just the body of test3
    @Override
    public g() { }
    @Override
    public h() { }
}

class Bbb extends C {}
class Ccc extends C {}

Затем, когда нужно предоставить конкретный C:

    C c;
    switch (a) {
    case "aaa": c = new Aaa(); break;
    case "bbb": c = new Bbb(); break;
    case "ccc": c = new Ccc(); break;
    ...
    }

    c.f(...);

    c.g(...);

    c.h(...);

Это выглядит косвенно, но в действительности обеспечивает улучшение качества разработки.Добавление нового регистра не означает поиск во всех регистрах переключений.

Код одного регистра («aaa») находится в одном классе с собственными выделенными полями.Это может упростить вещи и улучшить обзор.

0 голосов
/ 01 марта 2019

Я не совсем уверен, чего вы хотите достичь.Если вы не хотите продолжать добавлять новые

case ("ccc"):
  Lmn(b,c,i);
  break;         

блоки.

Вы можете хэшировать методы в HashMap<string, method>, получать метод из карты с помощью ключа и выполнять его..

...