繁体   English   中英

编写此 java 代码的最简洁/最佳方式是什么?

[英]What's the most concise / best way to write this java code?

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

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 都会向它传递一堆空值。

我可以重写它以使其更简洁吗? 如果是这样,你能举个例子吗?

一方面,我会使用增强的 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
      }
    }
  }
}

我想我会重构它以传递一个“动作”来调用每个客户端,并使用来自调用站点的匿名内部 class:

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 语句更好。

使用 generics

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

变成

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

此外,用 switch/case 替换方法也不是很好,尤其是当您需要为未使用的值传递虚拟参数时。 保留单独的方法。

我不知道如何使您的方法更简洁,但是我对 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 方法,从而减少对空值的需求。

根据上下文(有时安全管理器或代理会妨碍),内省和可变参数是您的朋友:

你可以有类似的东西:

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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM