使用几乎完全重复的代码但对其他方法的不同调用来重构函数

Refactoring functions with nearly entirely duplicate code but different calls to other methods

我正在学习 Java 并且正在学习在线课程等,我正在进行其中一项编码练习,并意识到我的两种方法之间存在大量重复,发现如下:

private static void addCustomerTransaction() {
    System.out.println("Enter the branch name:");
    String branchName = scanner.nextLine();

    System.out.println("Enter the customer name:");
    String customerName = scanner.nextLine();

    System.out.println("Enter the transaction");
    while (!scanner.hasNextDouble()) {
        scanner.next();
    }
    double transaction = scanner.nextDouble();

    bank.addCustomerTransaction(branchName,customerName,transaction);

}

private static void addCustomer() {
    System.out.println("Enter the branch name:");
    String branchName = scanner.nextLine();

    System.out.println("Enter the customer name:");
    String customerName = scanner.nextLine();

    System.out.println("Enter the transaction");
    while (!scanner.hasNextDouble()) {
        scanner.next();
    }
    double transaction = scanner.nextDouble();

    bank.addCustomer(branchName,customerName,transaction);
}

现在显然这两个函数之间的唯一区别是对银行 class 对象的方法调用 - 最终执行不同的操作。

我想知道如何重构这些方法以减少重复。我得到了:

private static void addCustomerTransaction() {
    customerInput();

}

private static void addCustomer() {
    customerInput();
}

private static void customerInput() {
    System.out.println("Enter the branch name:");
    String branchName = scanner.nextLine();

    System.out.println("Enter the customer name:");
    String customerName = scanner.nextLine();

    System.out.println("Enter the transaction");
    while (!scanner.hasNextDouble()) {
        scanner.next();
    }
    double transaction = scanner.nextDouble();

    bank.addCustomerTransaction(branchName,customerName,transaction);
}

但我不知道如何启用代码来更改方法调用(目前 bank.addCustomerTransaction(branchName,customerName,transaction);customerInput 函数中根据哪个函数调用 customerInput.

有人可以建议下一步吗?

您可以使它们成为一个函数,并使用另一个参数定义您是否要将其作为 addCustomerTransaction 或 addCustomer ,如下所示:

private static void addCustomer(boolean transaction) {
System.out.println("Enter the branch name:");
String branchName = scanner.nextLine();

System.out.println("Enter the customer name:");
String customerName = scanner.nextLine();

System.out.println("Enter the transaction");
while (!scanner.hasNextDouble()) {
    scanner.next();
}
double transaction = scanner.nextDouble();

if( transaction ) {
       bank.addCustomerTransaction(branchName,customerName,transaction);
  } else {
      bank.addCustomer(branchName,customerName,transaction);
  }
}

这是一种选择。

为最后一个方法创建接口:

@FunctionalInterface public interface CustomerOperation {
  void apply(Bank bank, String branch, String customer, String transaction);
}

那么你的常用方法可以是这样的:

private static void customerInput(CustomerOperation operation) {
  //common code here
  operation.apply(bank, branchName, customerName, transaction);
}

你这样称呼它:

private static void addCustomerTransaction() {
  customerInput((bank, branchName, customerName, transaction) ->
      bank.addCustomerTransaction(branchName, customerName, transaction));
}

private static void addCustomer() {
  customerInput((bank, branchName, customerName, transaction) ->
      bank.addCustomer(branchName, customerName, transaction));
}

或使用方法参考:

private static void addCustomerTransaction() {
  customerInput(Bank::addCustomerTransaction);
}

private static void addCustomer() {
  customerInput(Bank::addCustomer);
}

如何创建包含用户输入的 class?

public class TransactionInfo {

  private String branchName;
  private String customerName;
  private Double transaction;

  public TransactionInfo(String branchName, String customerName, Double transaction) {
    this.branchName = branchName;
    this.customerName = customerName;
    this.transaction = transaction;
  }

  ...
}

private static TransactionInfo customerInput() {
  System.out.println("Enter the branch name:");
  String branchName = scanner.nextLine();

  System.out.println("Enter the customer name:");
  String customerName = scanner.nextLine();

  System.out.println("Enter the transaction");
  while (!scanner.hasNextDouble()) {
    scanner.next();
  }
  double transaction = scanner.nextDouble();

  return new TransactionInfo(branchName, customerName, transaction);
}

private static void addCustomerTransaction() {
  TransactionInfo transactionInfo = customerInput();
  bank.addCustomerTransaction(transactionInfo.getBranchName(), transactionInfo.getCustomerName(), transactionInfo.getTransaction());
}

private static void addCustomer() {
  TransactionInfo transactionInfo = customerInput();
  bank.addCustomer(transactionInfo.getBranchName(), transactionInfo.getCustomerName(), transactionInfo.getTransaction());
}

如果您可以控制 bank 的 class,您可以考虑让 addCustomeraddCustomerTransaction 方法接受 TransactionInfo 作为参数.

另外,class 可能有一个比 TransactionInfo 更好的名字。但我希望你能明白。

您将通用代码提取到方法中的想法是正确的。您可以看到,与您的方法相比,我的解决方案基本上只为客户输入添加一个 class 以用作 customerInput 方法的 return 值。祝你好运:)

private static double readTransaction() {
    System.out.println("Enter the transaction");
    while (!scanner.hasNextDouble()) {
        scanner.next();
    }
    double transaction = scanner.nextDouble();
    return transaction;
}

private static String readCustomerName() {
    System.out.println("Enter the customer name:");
    String customerName = scanner.nextLine();
    return customerName;
}

private static String readBranch() {
    System.out.println("Enter the branch name:");
    String branchName = scanner.nextLine();
    return branchName;
}

private static void addCustomer() {
    String branchName = readBranch();
    String customerName = readCustomerName();
    double transaction = readTransaction();
    bank.addCustomer(branchName,customerName,transaction);
}

private static void addCustomerTransaction() {
    String branchName = readBranch();
    String customerName = readCustomerName();
    double transaction = readTransaction();
    bank.addCustomerTransaction(branchName,customerName,transaction);
}

此外,您可以Preserve Whole Object制作一个包含分行名称、客户名称和交易的class,然后执行以下操作:

class Receipt {
    private String customerName;
    private String branchName;
    private double transaction;

    //Getters and setters...

    public void populateReceipt () {
        customerName = readCustomer();
        branchName = readBranch();
        transaction = readTransaction();
    }
}

其次是...

private void addCustomer (Receipt receipt) {
    //Modify the method to take in a receipt, rather than its 3 components
    bank.addCustomer(receipt);
}

private void addCustomerTransaction (Receipt receipt) {
    //Modify the method to take in a receipt, rather than its 3 components
    bank.addCustomerTransaction(receipt);
}