为了账号安全,请及时绑定邮箱和手机立即绑定

违反 Java 中的 DRY 原则

违反 Java 中的 DRY 原则

四季花海 2021-11-11 10:54:40
我有三种方法可以按字段过滤一组设备。public void filtrateByType(Device[] devices, String type) {    if (devices == null) {        return;    }    for (int i = 0; i < devices.length; i++) {        if (devices[i] == null) {            continue;        }        if (devices[i].getType() == null && type == null) {            continue;        } else if (devices[i].getType() == null) {            devices[i] = null;            continue;        }        if (!devices[i].getType().equals(type)) {            devices[i] = null;        }    }}其他方法类似。唯一的区别是调用另一个应用过滤的字段的 getter。例如,有一个对getModel()instead的调用getType()。这是否违反了 DRY 原则,我该如何更改它以使其不会(没有泛型)?PS 这是一个家庭作业,不幸的是我们还没有使用泛型。我也无法更改方法的签名。我有一个线索,我可以使用一种方法创建内部类,该方法将调用所需的 getter 并返回一个值。所以,我需要把我所有的检查都放在这个方法中,但我真的不明白我的逻辑是怎么做的(尤其是“继续”)。
查看完整描述

3 回答

?
SMILET

TA贡献1796条经验 获得超4个赞

你可以创建一个interface DeviceValueExtractor看起来像这样的:


@FunctionalInterface

public interface DeviceValueExtractor {

    Object extractValue(Device device);

}

现在将您的方法重写为:


public void filterByType(Device[] devices, DeviceValueExtractor extractor, Object expect) {

    if (devices == null) {

        return;

    }

    for (int i = 0; i < devices.length; i++) {

        if (devices[i] == null) {

            continue;

        }

        Object actual = extractor.extractValue(devices[i]);

        if (actual == null && expect== null) {

            continue;

        } else if (actual  == null) {

            devices[i] = null;

            continue;

        }

        if (!Objects.equals(actual, expect)) {

            devices[i] = null;

        }

    }

 }

用法:


filterByType(devices, Device::getType, "Hello");

注意:我使用是Object因为要求没有泛型 - 因为调用的唯一方法是equals这实际上没什么大不了的。


但是,对于更多类型安全性,您可以引入泛型(并取消DeviceValueExtractor:


public static <T> void filterByType(Device[] devices, Function<Device, T> extractor, T expect) {

    if (devices == null) {

        return;

    }

    for (int i = 0; i < devices.length; i++) {

        if (devices[i] == null) {

            continue;

        }

        Object actual = extractor.apply(devices[i]);

        if (actual == null && expect== null) {

            continue;

        } else if (actual  == null) {

            devices[i] = null;

            continue;

        }

        if (!Objects.equals(actual, expect)) {

            devices[i] = null;

        }

    }

}


查看完整回答
反对 回复 2021-11-11
?
catspeake

TA贡献1111条经验 获得超0个赞

也许一些 Java 8 魔法会在这里有所帮助:


public void filtrateByType(Device[] devices, String type) {

    filtrateBy(devices, Device::getType, type);

}


public void filtrateBy(Device[] devices, Function<? super Device, String> attributeGetter, String attribute) {

    if (devices == null) {

        return;

    }

    for (int i = 0; i < devices.length; i++) {


        if (devices[i] == null) {

            continue;

        }


        if (attributeGetter.apply(devices[i]) == null && attribute == null) {

            continue;

        } else if (attributeGetter.apply(devices[i]) == null) {

            devices[i] = null;

            continue;

        }

        if (!attributeGetter.apply(devices[i]).equals(attribute)) {

            devices[i] = null;

        }

    }

}


查看完整回答
反对 回复 2021-11-11
?
炎炎设计

TA贡献1808条经验 获得超4个赞

这是更简单的版本。您可以使用原始类型,但这会更容易出错。


public static <T> void filtrateByType(T[] objects, Function<T, String> function, String type) {

    if (objects == null || type == null)

        return;

    for (int i = 0; i < objects.length; i++) {

        if (objects[i] == null) continue;

        String match = function.apply(objects[i]);

        if (match == null || !match.equals(type)) 

            objects[i] = null;

    }

}

但是,我怀疑您真正想要的是使用 Stream API


Device[] filtered = Stream.of(devices)

                          .filter(d -> Objects.equals(d.getType(), type))

                          .toArray(Device[]::new);


查看完整回答
反对 回复 2021-11-11
  • 3 回答
  • 0 关注
  • 189 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信