Java 最小化类中的代码重复?

Java 最小化类中的代码重复?,java,oop,optimization,design-patterns,Java,Oop,Optimization,Design Patterns,我使用下面的类通过使用套接字以同步方式或异步方式向消息队列发送数据,如下所示 到目前为止,我在我的下课中复制了很多代码。下面我有5个方法,用于同步或异步发送数据,我相信有更好的方法重写这些方法 public class SendRecord { private final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2); private final Cache<Long,

我使用下面的类通过使用套接字以同步方式或异步方式向消息队列发送数据,如下所示

到目前为止,我在我的下课中复制了很多代码。下面我有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);
    }
  }
}
公共类SendRecord{
private final ScheduledExecutorService executorService=Executors.newScheduledThreadPool(2);
专用最终缓存=
缓存生成器
.newBuilder()
.最大尺寸(2000000)
.concurrencyLevel(100.build();
私有静态类持有者{
私有静态最终SendRecord实例=新SendRecord();
}
公共静态SendRecord getInstance(){
返回持有者实例;
}
私有SendRecord(){
executorService.scheduleAtFixedRate(新的Runnable(){
@凌驾
公开募捐{
手工艺学();
}
},0,1,时间单位为秒);
}  
私人空间手工艺品(){
列表消息=新的ArrayList(cache.asMap().values());
用于(PendingMessage消息:消息){
if(message.hasExpired()){
if(message.shouldRetry()){
message.markResent();
doSendAsync(消息);
}否则{
cache.invalidate(message.getAddress());
}
}
}
}
//由多个线程并发调用
公共布尔sendAsync(最终长地址,最终字节[]编码记录){
PendingMessage m=新的PendingMessage(地址,编码记录,true);
cache.put(地址,m);
返回dosendascync(m);
}
//通过上述方法调用,也可以通过HandlerMethod调用
专用布尔值doSendAsync(最终PendingMessage PendingMessage){
可选liveSocket=SocketManager.getInstance().getNextSocket();
ZMsg msg=新的ZMsg();
添加(pendingMessage.getEncodedRecords());
试一试{
//这会立即返回
返回msg.send(liveSocket.get().getSocket());
}最后{
msg.destroy();
}
}
//由下面的send方法调用
私有布尔dosendascent(最终PendingMessage PendingMessage,最终套接字){
ZMsg msg=新的ZMsg();
添加(pendingMessage.getEncodedRecords());
试一试{
//这会立即返回
返回msg.send(套接字);
}最后{
msg.destroy();
}
}
//由多个线程调用以在不通过套接字的情况下同步发送数据
公共布尔发送(最终长地址,最终字节[]编码记录){
PendingMessage m=新的PendingMessage(地址,编码记录,false);
cache.put(地址,m);
试一试{
if(doSendAsync(m)){
返回m.waitForAck();
}
返回false;
}最后{
cache.invalidate(地址);
}
}
//由线程调用以同步发送数据,但以套接字作为参数
公共布尔发送(最终长地址、最终字节[]编码记录、最终套接字){
PendingMessage m=新的PendingMessage(地址,编码记录,false);
cache.put(地址,m);
试一试{
if(doSendAsync(m,套接字)){
返回m.waitForAck();
}
返回false;
}最后{
cache.invalidate(地址);
}
}
公共无效handleAckReceived(最终长地址){
PendingMessage记录=cache.getIfPresent(地址);
if(记录!=null){
record.ackReceived();
cache.invalidate(地址);
}
}
}

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

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

  • 切换到Kotlin
  • 您可以在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)
    


  • 将默认属性发送到更复杂的方法
  • 如果您想使用Java,请执行以下操作

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

    乍一看,您可以多次使用“Extract方法”进行重构

    此代码重复:

    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);
        }
    
    因此,从中找出另一种方法


    一般来说,有一本关于重构的经典而优秀的书

    我投票将这个问题作为离题题来结束,因为审查工作代码的请求属于codereview.stackexchange.com
    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);
        }