解决冗余代码的三种方法,让你的代码更上一层楼( 二 )

我们正在 FtpOperationTemplate? 上执行方法 execute? 并且我们正在传递 lambda? 表达式 。我们将放入 lambda? 中的所有逻辑都将代替 ftpOperation.apply(ftpClient) 函数执行 。
3. 模板方法

  • 创建一个抽象的模板类
@RequiredArgsConstructor@Slf4j@Serviceabstract class FtpOperationTemplate<T, K> {protected abstract K command(FTPClient ftpClient, T input) throws IOException;public K execute(FTPClient ftpClient, T input) {try {ftpClient.connect("host", 22);ftpClient.login("username", "password");return command(ftpClient, input);} catch (IOException ex) {log.error("Something went wrong", ex);throw new RuntimeException(ex);} finally {try {ftpClient.logout();ftpClient.disconnect();} catch (IOException ex) {log.error("Something went wrong while finally", ex);}}}}
  • 列出ftp目录listDirectories方法的实现
@Slf4j@Serviceclass FtpOperationListDirectories extends FtpOperationTemplate<String, FTPFile[]> {@Overrideprotected FTPFile[] command(FTPClient ftpClient, String input) throws IOException {return ftpClient.listDirectories(input);}}
  • 删除文件deleteFile方法的实现
 @Slf4j@Serviceclass FtpOperationDeleteFile extends FtpOperationTemplate<String, Boolean> {@Overrideprotected Boolean command(FTPClient ftpClient, String input) throws IOException {return ftpClient.deleteFile(input);}}
  • 实现FtpProvider接口
 @RequiredArgsConstructor@Slf4j@Servicepublic class FtpProviderTemplateImpl implements FtpProvider {private final FtpOperationTemplate<String, FTPFile[]> ftpOperationListDirectories;private final FtpOperationTemplate<String, Boolean> ftpOperationDeleteFile;private final FTPClient ftpClient;public FTPFile[] listDirectories(String parentDirectory) {return ftpOperationListDirectories.execute(ftpClient, parentDirectory);}public boolean deleteFile(String filePath) {return ftpOperationDeleteFile.execute(ftpClient, filePath);}}我们正在 FtpOperationTemplate? 上执行方法 execute? 并在那里传递我们的参数 。因此执行方法的逻辑对于 FtpOperationTemplate 的每个实现都是不同的 。
总结我们现在来比较下上面种方式:
  • @Aspect切面方式实现
向 FtpProvider? 接口添加一个新方法,需要我们仅在一个地方进行更改 。我们可以轻松地将我们的 FtpProvider? 注入到其他服务中 。此解决方案的强项可能是 @FtpOperation? 注释,它可以在 FtpProvider 上下文实现之外使用,但是将 Ftp 操作的逻辑划分到单独的类中并不是一个好方法 。
  • 函数式接口实现
向接口 FtpProvider? 添加一个新方法,需要我们仅在一个地方进行更改 。我们可以轻松地将我们的 FtpProvider 注入到其他服务中 。我们将ftp操作的逻辑封装在一个类中 。相对于上面的方式,我们也没有用到AOP的库,所以我个人还是比较推荐的 。
  • 模板方法实现
向接口 FtpProvider? 添加一个新方法,需要我们在两个地方进行更改 。我们需要添加一个新的类,会导致类爆炸,另外,我们还需要将实现注入到 FtpProvider 。
如果是你,你会选择哪种方式呢?还是有更好的方法?

【解决冗余代码的三种方法,让你的代码更上一层楼】


推荐阅读