java - 最佳实践 : get deep value of an object

标签 java

在java中,我通常必须获取该对象深处的对象的属性值。例如,如果我确定所有子对象都不为空,我可以这样做:

public function getDeepValue(A a) {

    String value = a.getB().getC().getListeD().get(0).getE().getValue();
    return value;
}

但是如果父对象的子对象可以为空,我必须测试每个对象。
为此,我看到了 2/3 的解决方案:

首先,一步一步:

public function getDeepValue(A a) {

    if(a == null){
        return null;
    }

    B b = a.getB();
    if(b == null) {
        return null;
    }

    C c = b.getC();
    if(c == null){
        return null;
    }

    List<D> ds = c.getListeD();
    if(ds == null || ds.size() == 0){
        return null;
    }

    D d = ds.get(0);
    if(d == null) {
        return null;
    }

    E e = d.getE()
    if(e == null){
        return null;
    }

    return e.getValue();
}

第二,在一个 if block 中测试所有内容,太脏了:

public function getDeepValue(A a) {

    if(a != null && a.getB() != null && a.getB().getC() != null && a.getB().getC().getListeD() != null && a.getB().getC().getListeD().size() > 0 && a.getB().getC().getListeD().get(0) != null && a.getB().getC().getListeD().get(0).getE() != null){
        return a.getB().getC().getListeD().get(0).getE().getValue();
    }

    return null;
}

第三种解决方案,使用 try catch block :

public function getDeepValue(A a) {

    try {
        return a.getB().getC().getListeD().get(0).getE().getValue();

    } catch(NullPointerException e) {
        return null;

    } catch(IndexOutOfBoundsException e) {
        return null;
    }
}

解决方案 1 看起来还不错,但需要大量代码。这通常是我使用的解决方案。
解决方案 2 对我来说真的很脏......
在纸面上,我真的很喜欢解决方案 3,但就性能而言,它是一个好的解决方案吗?

还有其他可接受的解决方案吗?
感谢您的帮助,我希望我的英语不会太差..
问候

最佳答案

解决方案 #3 看起来很简单,但它可能隐藏了一大堆问题。如果您可以完全访问链中的所有类,并且您知道每个方法中发生了什么,并且您可以保证这些方法不会导致您的 try/出现问题,那么它可能是一个足够的解决方案catch 并且你永远不会改变它们......这是使其成为一个有值(value)的解决方案的很多条件,但我可以想象它可能是一个有用足够的解决方案。

解决方案 #2 对我来说看起来很可怕,特别是如果一个或多个 get 方法是瓶颈(例如缓慢的数据库查询或使用阻塞的网络连接)。正如您一遍又一遍地调用的那样,这种潜在瓶颈在链条中越早,情况可能就越糟糕。这当然取决于相关方法的实现(例如,即使其中一个方法很慢,结果也可以被缓存),但您不应该需要知道在您的客户端中代码。即使实现高效或简单,您仍然会承受不必要的重复方法调用的开销。

解决方案 #1 是三个中最好的,但它可能不是最好的。可能。该解决方案比其他两个解决方案需要更多的代码行,但它不会重复本身,也不会被其他方法的实现所绊倒。 (注意:如果您无法访问链中的类进行重构,我将使用此解决方案。)

比#1 更好的解决方案是重构类,以便客户端代码根本不需要了解此链。。大致如下:

class Client {
    public Mumble getDeepValue(A a) { return a == null ? null : a.getDeepValue(); }
}

class A {
    private B b;
    public Mumble getDeepValue() { return b == null ? null : b.getDeepValue(); }
}

class B {
    private C c;
    public Mumble getDeepValue() { return c == null ? null : c.getDeepValue(); }
}

class C {
    private List<D> ds;
    public Mumble getDeepValue() {
        D d = ds == null || ds.size() == 0 ? null : ds.get(0);
        return d == null ? null : d.getDeepValue();
    }
}

class D {
    private E e;
    public Mumble getDeepValue() { return e == null ? null : e.getMumble(); }
}

class E {
    private Mumble m;
    public Mumble getMumble() { return m; }
}

正如您所看到的,这些类中的任何一个具有的最长链都是访问属于该类的私有(private)成员的集合元素的公共(public)成员。 (本质上是ds.get(0).getDeepValue())客户端代码不知道兔子洞有多深,只知道A公开了一个返回a的方法咕哝Client 甚至不需要知道类 BCDEList 存在于任何地方!

此外,如果我从头开始设计这个系统,我会仔细考虑是否可以对其进行重组,以使实际的 Mumble 对象不那么深。如果我可以合理地将 Mumble 存储在 AB 中,我建议这样做。然而,根据应用程序的不同,这可能是不可能的。

关于java - 最佳实践 : get deep value of an object,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26489866/

相关文章:

java - 在 AngularJS 中显示 POM 版本号

java - 绘制可运行的 JPanel

java - 如何为shift+8(*)或java中的任意两个键添加KeyListenet

java - Tomcat 和 MYSQL 移植到 AWS

java - Setter - 检查值

java - 使用 Tomcat6 实现 cometd 模式

java - Doc4j pptx查找并替换表格行

java - 根据 If 语句更改 JOptionPane 背景颜色

java - 如何在线程安全环境中定义静态Arraylist

java - Autowiring 工厂创建实例的 spring 方法是什么?