2009-03-31 4 views
1

Я пишу простое приложение, распределенная Java RMI и у меня есть куча методов, каждый нужно перебирать карту клиентских интерфейсов для того, чтобы вызвать различные другие методы этих интерфейсов, например:Какой самый сжатый/лучший способ написать этот Java-код?

public void methodX (arg1, arg2) { 
    Iterator<String> itr = clients.keySet().iterator; 
    while (itr.hasNext()) { 
    String name = itr.next(); 
    if (!"mod".equals(name)) { 
     try { 
     clients.get(name).methodXX(arg1, arg2); 
     } catch(RemoteException ex) { 
     // do something 
     } 
    } 
    } 
} 

public void methodY (arg1, arg2, arg3) { 
    Iterator<String> itr = clients.keySet().iterator; 
    while (itr.hasNext()) { 
    String name = itr.next(); 
    if (!"mod".equals(name)) { 
     try { 
     clients.get(name).methodYY(arg1, arg2, arg3); 
     } catch(RemoteException ex) { 
     // do something 
     } 
    } 
    } 
} 

Теперь я изменил их так, что вместо того, чтобы каждый из них называют один метод DOALL, передавая новый аргумент с именем MESSAGE_TYPE, например, так:

public void methodX (arg1, arg2) { 
    doAll(MESSAGE_TYPE.METHODX, arg1, arg2, null); 
} 

public void methodY (arg1, arg2, arg3) { 
    doAll(MESSAGE_TYPE_METHODY, arg1, arg2, arg3); 
} 

и метод DOALL:

public void doAll(msg_type, arg1, arg2, arg3) { 
Iterator<String> itr = clients.keySet().iterator; 
    while (itr.hasNext()) { 
    String name = itr.next(); 
    if (!"mod".equals(name)) { 
     try { 
     switch(msg_type) { 
      case METHODX: 
      clients.get(name).methodXX(arg1, arg2); 
      break; 
      case METHODY: 
      clients.get(name).methodYY(arg1, arg2, arg3); 
      break; 
     } 
     } catch(RemoteException ex) { 
     // do something 
     } 
    } 
    } 
} 

Теперь есть еще много таких методов, поэтому мой метод doAll должен взять кучу аргументов и каждый методXX, который вызывает его, передает ему множество нулей.

Могу ли я переписать это, чтобы оно было более кратким? Если да, можете ли вы привести пример?

+1

«... прост в распространении java rmi application ...» oxymoron much? –

ответ

9

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

public void doAll(arg1, arg2, arg3) { 
    for (Map.Entry<String,Client> entry : clients.entrySet()) { 
    if (!"mod".equals(entry.getKey())) { 
     try { 
     switch(MESSAGE_TYPE) { 
      case METHODX: 
      entry.getValue().methodXX(arg1, arg2); 
      break; 
      case METHODY: 
      entry.getValue().methodYY(arg1, arg2, arg3); 
      break; 
     } 
     } catch(RemoteException ex) { 
     // do something 
     } 
    } 
    } 
} 

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

public interface RemoteAction { 
    public void execute(Client client) throws RemoteException; 
} 

public void doAll(RemoteAction action) { 
    for (Map.Entry<String,Client> entry : clients.entrySet()) { 
    if (!"mod".equals(entry.getKey())) { 
     try { 
     action.execute(entry.getValue()); 
     } catch(RemoteException ex) { 
     // do something 
     } 
    } 
    } 
} 

public void methodX (final arg1, final arg2) { 
    doAll(new Action() { 
    @Override public void execute(Client client) throws RemoteException { 
     client.methodX(arg1, arg2); 
    } 
    }); 
} 

public void methodY (final arg1, final arg2, final arg3) { 
    doAll(new Action() { 
    @Override public void execute(Client client) throws RemoteException { 
     client.methodY(arg1, arg2, arg3); 
    } 
    }); 
} 

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

+0

Итерации над entrySet вместо вызова «get» с keySet, и я думаю, что у вас есть победитель. – erickson

+0

Я думал об этом, да. Хорошо, изменит ответ :) –

0

Использование дженериков

Iterator<String> itr = clients.keySet().iterator; 
while (itr.hasNext()) { 
    String name = itr.next(); 

становится

for(String name: clients.keySet()){ 

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

-2

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

Вы могли бы что-то вроде:

void callStuff(String methodName, Object ... args) 
{ 
    for(Client client: clients) 
    { 
    //...filter client by name, method, etc. 
    //...figure out parameter types - you can guess from args or pass another parameter 
    Method method = client.getClass().getMethod(methodNamename, parameterTypes); 
    method.invoke(client,args); 
    } 
} 

(Отказ от ответственности: код выше не проверено, а не компилируется событие, и я не знаю, будет ли он работать с RMI)

-1

Я не знаю, как сделать ваш метод более кратким, но у меня есть предложения по параметрам метода doAll ...

public void doAll(int methodType, Object... arg) 
{ 
    //snip 
    switch(msg_type) 
    { 
     case METHODX: 
      clients.get(name).methodXX(arg[0], arg[1]); 
      break; 
     case METHODY: 
      clients.get(name).methodYY(arg[0], arg[1], arg[2]); 
      break; 
    } 
    //snip 
} 

Это позволит вам передать переменное количество аргументов методу doAll, облегчив необходимость в нулях.

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