2016-05-12 4 views
4

Рассмотрим методJava - реализация метода зависит от значения параметра

public void doSomething(String actionID){ 
switch (actionID){ 
    case "dance": 
      System.out.print("I'm dancing"); 
      break; 
    case "sleep": 
      System.out.print("I'm sleeping"); 
      break; 
    default: 
      System.out.print("I've no idea what I'm doing"); 
} 

Реализация метода зависит от значения параметра. Есть ли более элегантный способ сделать это или другой шаблон дизайна для повторения поведения?

+0

Может быть, возможно, что вы ищете что-то вроде этого ? http://crunchify.com/why-and-for-what-should-i-use-enum-java-enum-examples/ –

+4

Вы можете реализовать шаблон команды. –

ответ

0

Вот простая реализация шаблона команды, основанного на вашей проблеме с образцом. Я определяю абстрактный класс AbstractCommand, который содержит два метода. Первый метод, createCommand(), создает экземпляр класса команд на основе имени входной строки. Именно так вы можете делегировать свой ввод строки, чтобы создать правильный тип команды. Второй метод - doAction(), и это остается неопределенным, который будет реализован позже конкретными конкретными командами.

public abstract class AbstractCommand { 
    public static AbstractCommand createCommand(String name) { 
     try { 
      String clsName = name + "Command"; 
      Class<?> cls = Class.forName(clsName); 
      AbstractCommand command = (AbstractCommand) cls.newInstance(); 

      return command; 
     } 
     catch (Exception e) { 
      System.out.println("Something went wrong."); 
     } 
    } 

    public abstract void doAction(); 
} 

public class DanceCommand extends AbstractCommand { 
    public void doAction() { 
     System.out.println("I'm dancing"); 
    } 
} 

public class TestCommandPattern { 
    public void doSomething(String actionID) { 
     AbstractCommand cmd = AbstractCommand.createCommand(actionID); 
     cmd.doAction(); 
    } 

    public static void main(String[] args) { 
     TestCommandPattern test = new TestCommandPattern(); 
     test.doSomething("Dance"); // should print "I'm dancing" 
    } 
} 

Теперь, когда эта инфраструктура была настроена, вы можете легко добавить другие команды для различных типов действий в своей исходной проблеме. Например, вы можете создать класс SleepCommand, который будет выводить I'm sleeping или выполнять любые действия.

4

Если абонент решает, что логика выполняется путем передачи различных строк, то почему бы не просто их называют различные методы:

public void doSomething(String actionID) {...} 
... 
doSomething("dance"); 
doSomething("sleep"); 

VS .:

public void dance() {...} 
public void sleep() {...} 
... 
dance(); 
sleep(); 

Похоже, вы излишне утекают все звонки в doSomething


Но струны могут быть не всегда литералами. Что делать, если вы берете их с консоли?

Вы можете создать статические сопоставления из строк с соответствующими функциями:

class MyClass { 
    private static final Map<String, Consumer<MyClass>> map = new HashMap<>(); 

    static { 
     map.put("sleep", MyClass::sleep); 
     map.put("dance", MyClass::dance); 
    } 

    public void doSomething(String actionID) { 
     map.getOrDefault(actionID, MyClass::doNothing).accept(this); 
    } 

    public void dance() { 
     System.out.print("I'm dancing"); 
    } 

    public void sleep() { 
     System.out.print("I'm sleeping"); 
    } 

    private void doNothing() { 
     System.out.println("I've no idea what I'm doing"); 
    } 
} 

Это делает сценарии, в которых у вас есть много случаев переключателя намного чище.

1

Ввести интерфейс, например.

public interface HumanState { 

    public void tellMeWhatYouAreDoing(); 
    } 

инкапсулирует логику в различных реализациях

public class DancingState implements HumanState { 
    @Override 
    public void tellMeWhatYouAreDoing() { 
     System.out.println("I'm dancing"); 
    } 
    } 

    public class SleepingState implements HumanState { 

    @Override 
    public void tellMeWhatYouAreDoing() { 
     System.out.println("I'm sleeping"); 
    } 
    } 

    public class UnknownState implements HumanState { 

    @Override 
    public void tellMeWhatYouAreDoing() { 
     System.out.println("I've no idea what I'm doing"); 
    } 
    } 

и использовать карту. Например.

public class HumanStateExample { 

    public static void main(String[] args) { 
    HumanStateExample humanStateExample = new HumanStateExample(); 

    humanStateExample.doSomething("dance"); 
    humanStateExample.doSomething("sleep"); 
    humanStateExample.doSomething("unknown"); 
    } 

    private final HashMap<String, HumanState> humanStateMap; 


    public HumanStateExample(){ 
    humanStateMap = new HashMap<String, HumanState>(); 
    humanStateMap.put("dance", new DancingState()); 
    humanStateMap.put("sleep", new SleepingState()); 

    } 

    public void doSomething(String action) { 
    HumanState humanState = humanStateMap.get(action); 
    if(humanState == null){ 
     humanState = new UnknownState(); 
    } 

    humanState.tellMeWhatYouAreDoing(); 
    } 
} 
1

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

Создать много обработчиков, где каждый из них знает, когда отвечает за обработку вызова. Затем просто проведите через них и вызовите первый, соответствующий этому параметру.

редактировать: я переименовал класс от FancyParameterAction Factory до FancyParameterAction Utility: это не завод, название вводит в заблуждение

//Your method, but this time with a complex object, not with a simple string. 
public void doSomething(FancyParameterObject fpo){ 
    FancyParameterActionUtility.invokeOn(fpo); 
} 


//The utility which can handle the complex object and decides what to do. 
public class FancyParameterActionUtility{ 
    public Interface FPAHandler{ 
     void invoke(FancyParameterObject fpo); 
     boolean handles(FancyParameterObject fpo); 
    } 

    //Omitted: Different implementations of FPAHandler 

    public static List<FPAHandler> handlers = new LinkedList<>(); 

    static{ 
     handlers.add(new DanceHandler()); 
     handlers.add(new SleepHandler()); 
     //Omitted: Different implementations of FPAHandler 
    } 

    public static void invokeOn(FancyParameterObject fpo){ 
     for(FPAHandler handler:handlers){ 
      if (handler.handles(fpo)){ 
       handler.invoke(fpo); 
       return; 
      } 
     } 
     //Default-Behavior 
    } 

} 
Смежные вопросы