不那么冗长的懒惰加载方式



我正在重构一个名为ConfigNode的类,该类存储50个"属性"。每个属性都是自己的对象。所有属性都是可选的,大多数情况下,其中许多属性都没有设置。

目前,类的编写方式是,当它被实例化时,所有50个属性也都被实例化。当您创建一百万个Config对象时,Java告诉我正在使用2.5吉的内存。当我注释掉属性实例化时,Java说我使用的是300 MB。

我使用的基准代码是

Runtime.getRuntime().gc();
// do my stuff
Runtime.getRuntime().gc();
long memory = Runtime.getRuntime().totalMemory();
System.out.println("Memory used: " + memory / 1000000 + " MB");

因此,我正在考虑重写类,以便在访问属性时延迟加载属性,但必须编写类似的内容

// This is probably not thread safe, so it could be even more verbose
public NodeProperty propOne() {
   if (propOne == null) {
      propOne = new NodeProperty( ... )
   }
   return propOne
}

然后对所有属性执行此操作似乎有点冗长。Java中有什么可以帮助我减少必须编写的代码量(从而减少维护)吗?

以下是NodeConfig看起来像的样子

public class NodeConfig {
    public NodeProperty pVersion = new NodeProperty( "Spec Version", Status.REQUIRED, Visibility.HIDDEN);
    public NodeProperty pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE );
    public NodeProperty pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.HIDDEN);
    // more properties
    public NodeConfig() {
        // 
    }
}

Guava的供应商库可以为您完成所有延迟加载的逻辑(包括线程安全,而您的示例没有)。

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
private Supplier<NodeProperty> propOneSupplier =
    Suppliers.memoize(() -> new NodeProperty(...));
public NodeProperty propOne() {
    return propOneSupplier.get();
}

方法1
以下是在给定NodeConfig代码的情况下可以使用的另一种方法:公共类NodeConfig{

    public NodeProperty pTwoWay;
    public NodeProperty pBinary;
    // more properties
    public NodeConfig() {
        // 
    }
    public NodeProperty getProperty(NodePropertyEnum nodeProp) {
        switch(nodeProp) {
            case TWO_WAY: 
                if (pTwoWay != null) {return pTwoWay;}
                pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE ); 
            case BINARY_MODE: 
                if (pBinary != null) {return pBinary;}
                pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.VISIBLE); 
            // other cases
            default: 
                throw new IllegalArgumentException();
        }
    }
}

方法2
看起来像是Singleton设计模式的案例。与其检查propOne实例是否为null,不如将所有Property类设置为singleton。类似于:

public class NodeProperty {
    private static volatile NodeProperty instance = null;
    private NodeProperty() {
        // instantiatin logic
    }
    public NodeProperty getInstance() {
        if(instance == null) {
            synchronized(NodeProperty.class) {
                if(instance==null) {
                    instance = new NodeProperty();
                }
            } 
        }
    }
}

最新更新