2014-11-08 2 views
0

Я пытаюсь использовать RabbitMQ и на основе разных сообщений нужно вызывать различные инструменты.RabbitMQ - Вызов различных реализаций, основанных на разных условиях

Я установил формат сообщения как JSON, и есть поле «callType», значение которого является именем класса, реализующим общий интерфейс. например, все реализации реализуют интерфейс «Задача», и у меня есть реализация «TaskImp1», «TaskImp2», «TaskImp3».

Так что код должен быть как

if (callType=="TaskImp1") 
((Task)TaskImp1).runTask() 
if (callType=="TaskImp2") 
((Task)TaskImp2).runTask() 
if (callType=="TaskImp3") 
((Task)TaskImp3).runTask() 

Но это может быть более гибким? Если позже я разработаю новый «TaskImp4», я не хочу изменять вызывающий код, возможно ли, что Java автоматически выбирает правильную реализацию, поскольку callType на самом деле является именем класса реализации.

ответ

0

Sure: поместить экземпляры задач в карте:

private Map<String, Task> tasksByName = new HashMap<>(); 

... 

tasksByName.put("TaskImp1", new TaskImp1()); 
tasksByName.put("TaskImp2", new TaskImp2()); 
tasksByName.put("TaskImp3", new TaskImp3()); 

... 

String callType = message.getCallType(); 
Task task = tasksByName.get(callType); 
task.runTask(); 

Кроме того, читайте How do I compare strings in Java?

0

У вас есть возможность использовать Стратегию здесь. Так, например, вы можете сделать так:

public class MyTask { 
    private Task task; 
    public MyTask(Task task) { 
     this.task = task; 
    } 

    public void doSomething() { 
     task.runTask(); 
    } 

    public static void main(String args[]) { 
     MyTask task = new MyTask(new TaskImpl1());//or even you could use setTask() api to inject task at runtime rather than doing cast on compile time. 
     task.doSomething(); 
     task = new MyTask(new TaskImpl2()); 
     task.doSomething(); 
     task = new MyTask(new TaskImpl3()); 
     task.doSomething(); 
    } 
} 

Таким образом, вы можете сделать свой код расширяемым. Завтра, если у вас есть taskImpl4, вы можете самостоятельно его кодировать и вводить в MyTask, даже не затрагивая реализацию класса MyTask.

0

Поскольку @ovdsrn уже сказал, что вы можете использовать отражение. Простой пример будет что-то вроде (ключ getTask статический метод. Кроме того, обратите внимание, что при использовании Class.forName необходимо указать весь «путь» (пакет) для своего класса)

// ITask.java

package main; 

public interface ITask { 
    void doSomething(); 
} 

// Task1.java

package main; 

    public class Task1 implements ITask { 
     @Override 
     public void doSomething() { 
      System.out.println("Task1"); 
     }  
    } 

// Task2.java

package main; 

    public class Task2 implements ITask { 
     @Override 
     public void doSomething() { 
      System.out.println("Task2"); 
     }  
    } 

// главный

package main; 

public class JavaTest { 
    private static ITask getTask(String name) { 
     try { 
      Class<?> cls = Class.forName(name); 
      Object clsInstance = (Object) cls.newInstance(); 
      return (ITask)clsInstance; 
     } catch (Exception e) { // you can handle here only specific exceptions 
      return null; 
     } 
    } 

    public static void main(String[] args) { 
     String name = args.length > 0 ? args[0] : "Task2"; 
     ITask task = getTask("main." + name); 
     if (task != null) { 
      task.doSomething(); 
     } 
     else { 
      System.out.println("can not make instance of class: " + name); 
     } 
    } 
} 
Смежные вопросы