最小化类中的代码重复?

时间:2017-12-22 08:18:30

标签: java oop optimization design-patterns

我使用下面的类以同步方式或异步方式使用socket将数据发送到我们的消息队列。如下所示。

截至目前,我正在复制下面课程中的大量代码。我有5个方法用于同步或异步发送数据,我相信可能有更好的方法来重写这些方法。

public class SendRecord {
  private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
  private final Cache<Long, PendingMessage> cache =
      CacheBuilder
          .newBuilder()
          .maximumSize(2000000)
          .concurrencyLevel(100).build();

  private static class Holder {
    private static final SendRecord INSTANCE = new SendRecord();
  }

  public static SendRecord getInstance() {
    return Holder.INSTANCE;
  }

  private SendRecord() {
    executorService.scheduleAtFixedRate(new Runnable() {
      @Override
      public void run() {
        handleRetry();
      }
    }, 0, 1, TimeUnit.SECONDS);
  }  

  private void handleRetry() {
    List<PendingMessage> messages = new ArrayList<>(cache.asMap().values());
    for (PendingMessage message : messages) {
      if (message.hasExpired()) {
        if (message.shouldRetry()) {
          message.markResent();
          doSendAsync(message);
        } else {
          cache.invalidate(message.getAddress());
        }
      }
    }
  }

  // called by multiple threads concurrently
  public boolean sendAsync(final long address, final byte[] encodedRecords) {
    PendingMessage m = new PendingMessage(address, encodedRecords, true);
    cache.put(address, m);
    return doSendAsync(m);
  }

  // called by above method and also by handleRetry method
  private boolean doSendAsync(final PendingMessage pendingMessage) {
    Optional<SocketHolder> liveSocket = SocketManager.getInstance().getNextSocket();
    ZMsg msg = new ZMsg();
    msg.add(pendingMessage.getEncodedRecords());
    try {
      // this returns instantly
      return msg.send(liveSocket.get().getSocket());
    } finally {
      msg.destroy();
    }
  }

  // called by send method below
  private boolean doSendAsync(final PendingMessage pendingMessage, final Socket socket) {
    ZMsg msg = new ZMsg();
    msg.add(pendingMessage.getEncodedRecords());
    try {
      // this returns instantly
      return msg.send(socket);
    } finally {
      msg.destroy();
    }
  }

  // called by multiple threads to send data synchronously without passing socket
  public boolean send(final long address, final byte[] encodedRecords) {
    PendingMessage m = new PendingMessage(address, encodedRecords, false);
    cache.put(address, m);
    try {
      if (doSendAsync(m)) {
        return m.waitForAck();
      }
      return false;
    } finally {
      cache.invalidate(address);
    }
  }

  // called by a threads to send data synchronously but with socket as the parameter
  public boolean send(final long address, final byte[] encodedRecords, final Socket socket) {
    PendingMessage m = new PendingMessage(address, encodedRecords, false);
    cache.put(address, m);
    try {
      if (doSendAsync(m, socket)) {
        return m.waitForAck();
      }
      return false;
    } finally {
      cache.invalidate(address);
    }
  }

  public void handleAckReceived(final long address) {
    PendingMessage record = cache.getIfPresent(address);
    if (record != null) {
      record.ackReceived();
      cache.invalidate(address);
    }
  }
}

有没有更好的方法来重写上述方法?

2 个答案:

答案 0 :(得分:2)

乍一看,您可以使用&#34;提取方法&#34;重构几次。

此代码重复:

ZMsg msg = new ZMsg();
    msg.add(pendingMessage.getEncodedRecords());
    try {
      // this returns instantly
      return msg.send(liveSocket.get().getSocket());
    } finally {
      msg.destroy();
    }

所以从中创建类似private void sendMsg()的东西。 此代码也重复

PendingMessage m = new PendingMessage(address, encodedRecords, false);
    cache.put(address, m);
    try {
      if (doSendAsync(m, socket)) {
        return m.waitForAck();
      }
      return false;
    } finally {
      cache.invalidate(address);
    }

所以从中做出另一种方法。

总的来说,这是一本关于重构的经典优秀书籍https://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672

答案 1 :(得分:-1)

有两种方法可以减少java代码。

  1. 切换到Kotlin。
  2. 您可以在java项目中使用单个kotlin文件或转换整个项目。 Eclipse和Android Studio可以将整个项目从Java转换为Kotlin。

    您可以在Kotlin类中使用Java类,反之亦然。

    在Kotlin中,您可以使用默认参数。

    fun doSendAsync(pendingMessage: PendingMessage, socket: Socket = SocketManager.getInstance().getNextSocket().get().getSocket())
    

    如果传递了套接字,则会使用它。否则将使用SocketManager.getInstance()。getNextSocket()。get()。getSocket()。

    这是

    的方法声明
      private boolean doSendAsync(final PendingMessage pendingMessage, final Socket socket)
    

      private boolean doSendAsync(final PendingMessage pendingMessage) 
    
    1. 将默认属性发送给更复杂的方法。
    2. 如果要使用Java,请执行以下操作。

       private boolean doSendAsync(final PendingMessage pendingMessage) {
          return doSendAsync(pendingMessage), SocketManager.getInstance().getNextSocket().get().getSocket());
       }