Java -两个几乎相同的方法,但返回类型不同

fzwojiic  于 2023-04-10  发布在  Java
关注(0)|答案(1)|浏览(265)

我想知道如何避免在下面的示例中重复代码。我有两个方法,其中一个参数略有不同,返回的对象也略有不同(其中一个-简单-对象字段较少)

public class WarehouseSimpleSearchFilter {
    long companyId;
    private Set<Long> shipperIds;
    private Set<Long> carrierIds;
}
public class WarehouseSearchFilter extends WarehouseSimpleSearchFilter {
    long companyId;
    private String search;
    private Boolean isLocked;
}
private WarehouseSimpleSearchFilter getWarehouseSimpleSearchFilter(Set<Long> carrierIds, Set<Long> shipperIds, Authorization authorization, WarehouseSimpleSearchFilter searchFilter) {
        if (CollectionUtils.isEmpty(carrierIds) && CollectionUtils.isEmpty(shipperIds)) {
            final Set<Long> newCarrierIds = getCompanyId(WarehousePermission.READ_AVAILABLE, authorization);
            final Set<Long> newShipperIds = getCompanyIds(WarehousePermission.READ_COMPANY, authorization);
            searchFilter.setCarrierIds(newCarrierIds);
            searchFilter.setShipperIds(newShipperIds);
            return searchFilter;
        }
        if (!CollectionUtils.isEmpty(carrierIds)) {
            checkPermission(WarehousePermission.READ_AVAILABLE, authorization);
            searchFilter.setCarrierIds(Collections.unmodifiableSet(carrierIds));
        }
        if (!CollectionUtils.isEmpty(shipperIds)) {
            checkPermission(WarehousePermission.READ_COMPANY, authorization);
            searchFilter.setShipperIds(Collections.unmodifiableSet(shipperIds));
        }
        return searchFilter;
    }

    private WarehouseSearchFilter getWarehouseSearchFilter(Set<Long> carrierIds, Set<Long> shipperIds, Authorization authorization, WarehouseSearchFilter searchFilter) {
        if (CollectionUtils.isEmpty(carrierIds) && CollectionUtils.isEmpty(shipperIds)) {
            final Set<Long> newCarrierIds = getCompanyIds(WarehousePermission.READ_AVAILABLE, authorization);
            final Set<Long> newShipperIds = getCompanyIds(WarehousePermission.READ_COMPANY, authorization);
            searchFilter.setCarrierIds(newCarrierIds);
            searchFilter.setShipperIds(newShipperIds);
            return searchFilter;
        }
        if (!CollectionUtils.isEmpty(carrierIds)) {
            checkPermission(WarehousePermission.READ_AVAILABLE, authorization);
            searchFilter.setCarrierIds(Collections.unmodifiableSet(carrierIds));
        }
        if (!CollectionUtils.isEmpty(shipperIds)) {
            checkPermission(WarehousePermission.READ_COMPANY, authorization);
            searchFilter.setShipperIds(Collections.unmodifiableSet(shipperIds));
        }
        return searchFilter;
    }
iszxjhcz

iszxjhcz1#

看起来这些方法是相同的,但其中一个操作子类。你可以使用泛型一次性编写这些方法。

private <T extends WarehouseSimpleSearchFilter> T getWarehouseSimpleSearchFilter(
  Set<Long> carrierIds,
  Set<Long> shipperIds,
  Authorization authorization,
  T searchFilter
) {
  ...
}

但是,这里有几件事需要注意。
首先,看起来你总是只是改变searchFilter参数并返回它。如果是这种情况,你可以只返回void并接受WarehouseSimpleSearchFilter作为参数。返回传入的相同值没有意义,除非你设计的是fluent interface(并且有问题的参数不是你的例子中的接收者,所以这不适用于这里)。
第二,我对这里继承的使用提出质疑。你有一个父类,它似乎是一个“简单”的搜索过滤器,然后你子类化它来丰富功能。这是一个经典的反模式,曾经在学校里教过,你的“简单”搜索过滤器很可能变成一个fragile base class。继承应该建模一个“is-a”关系。我不知道搜索过滤器上有什么可用的方法,但命名约定本身就表明,“丰富的”搜索过滤器实际上并不是一个简单的搜索过滤器,看起来您使用继承作为实现便利的工具,而不是正确地对对象空间建模。
相反,我建议有一个接口来表示支持简单和丰富搜索过滤器的抽象API。如果两者之间有重要的共同功能,* 不 * 依赖于类的任何特定状态,那么它就可以分解为某个地方的静态方法或接口本身的默认方法。然后,每个搜索过滤器实现都可以是该接口的实现者,并且泛型函数可以将接口(或接口的有界泛型,如上所述)作为参数。

相关问题