获取相似对象属性的通用方法

Generalized method to get similar object attributes

我有一个对象,它有几个数组作为字段。 class 大致是这样的:

public class Helper {
    InsuranceInvoices[] insuranceInvoices;
    InsuranceCollectiveInvoices[] insuranceCollectiveInvoices
    BankInvoices[] bankInvoices;
    BankCollectiveInvoices[] bankCollectiveInvoices;
}

所有发票类型都有一个共同的标记界面发票
我需要获取所有发票才能对其调用另一种方法。

Helper helperObject = new Helper();
// ...

for (InsuranceInvoices invoice : helperObject.getInsuranceInvoices()) {
    Integer customerId = invoice.getCustomerId();
    // ...
}
for (BankInvoices invoice : helperObject.getBankInvoices()) {
    Integer customerId = invoice.getCustomerId();
    // ... 
}

// repeat with all array fields

问题是所有的发票只有标记界面是共同的。方法 getCustomerID() 不是由相互接口或 class 定义的。由于给定的规范,这是我无法更改的行为。

for-each-loop 中的代码重复让我很烦恼。我必须对四个不同数组中的所有发票对象执行完全相同的操作。因此,四个 for-each-loops 不必要地使代码膨胀。

有没有办法可以编写通用(私有)方法?一个想法是:

private void generalMethod(Invoice[] invoiceArray){
    // ...
}

但这需要四次 instanceof 检查,因为 class Invoice 不知道方法 getCusomterId()。因此,我将一无所获;该方法仍将包含重复。

我感谢所有可能的解决方案来概括这个问题!

它不漂亮,但是您可以使用反射来查找getCustomerId Method and then invoke() it, cf. Class.getDeclaredMethod()

private void generalMethod(Invoice[] invoiceArray){
  try {
    for (Invoice invoice : invoiceArray) {
      Method getCustomerId = invoice.getClass().getDeclaredMethod("getCustomerId");
      getCustomerId.invoke(invoice);
    }
  } catch (Exception e) {
    // ...
  }
}

请注意这是未经测试的。

如果不允许您通过向它们添加自定义界面来更改您正在处理的 classes。您可以做的最好的事情是用具有所需属性的自定义 class 包装它们。

通过这种方式,您将拥有一个 class,其中包含所有 'not so nice' 代码,可将您无法触及的 classes 转换为与适当且匹配的漂亮 classes有用的设计。

例如,您可以有一个扩展 WrappedInsurace 并包含成员字段 InsuranceInvoice 的 class WrappedInsuranceInvoice。如果您不需要保留原始 class ,那么复制数据会更好。这样您就可以例如丢失数组并改用列表。

概括问题的可能解决方案(从最好到最差排序):

使用包装器class

public class InvoiceWrapper {
    private String customerID;
    public String getCustomerID() {
        return customerID;
    }
    public InvoiceWrapper(BankInvoices invoice) {
       this.customerID = invoice.getCustomerID();
    }
    public InvoiceWrapper(InsuranceInvoices invoice) {
       this.customerID = invoice.getCustomerID();
    }
    // other constructors
}

Upd 如果我理解正确的话,你需要对所有数组中的 ID 做一些事情。要使用 InvoiceWrapper,您还需要在 Helper class 中实现迭代器,它将遍历数组和 return 每个条目的包装器。因此,无论如何,您将拥有适用于 4 个数组的代码。

使用转换实例

public class CustomerIdHelper {
    public static String getID(Invoice invoice) {
        if (invoice instanceof InsuranceInvoices) {
            return ((InsuranceInvoices) invoices).getCustomerID();
        } else if ...
    }
}

通过反射按名称调用方法

public class CustomerIdHelper {
    public static String getID(Invoice invoice) {
        Method method = invoice.getClass().getDeclaredMethod("getCustomerId");
        return (String) method.invoke(invoice);
    }
}