编写这个java代码最简洁/最好的方法是什么?

时间:2009-03-31 22:42:07

标签: java

我正在编写一个简单的分布式java rmi应用程序,我有一堆方法,每个方法都需要遍历客户端接口的映射,以便在这些接口上调用各种其他方法,如下所示:

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
      }
    }
  }
}

现在我修改了这些,以便它们通过传递一个名为MESSAGE_TYPE的新参数来调用单个方法doAll,如下所示:

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方法需要一堆args,每个调用它的methodXX都会传递一堆空值。

我可以重写一下这样更简洁吗?如果是这样,你能提供一个例子吗?

4 个答案:

答案 0 :(得分:9)

首先,我使用增强型for循环,并按照条目中的建议迭代条目而不是密钥:

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);
    }
  });
}

它不像支持lambda表达式的语言那样好,但它比switch语句更好。

答案 1 :(得分:0)

使用泛型

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

变为

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

此外,用switch / case替换方法并不是那么好,特别是如果你需要为未使用的值传递伪参数。保持单独的方法。

答案 2 :(得分:-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
}

这将允许您将可变数量的args传递给doAll方法,从而减少对空值的需求。

答案 3 :(得分:-2)

根据上下文(有时安全管理器或代理人会妨碍),内省和varargs是你的朋友:

你可以拥有类似的东西:

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)