编写具有许多可选属性的java对象的最佳方法

时间:2014-10-14 21:28:22

标签: java pojo

我必须编写一个用于保存计算结果的Java对象。结果包含大量可能设置或不设置的字段取决于所使用的算法类型。例如:

class EquityValuationResult {
    private ValuationAlgorithm algorithm;
    private int yield;
    private double curve;
    private double meanValue;
    private double probability;
    private int standardDeviation;
    private boolean approximateValue;
    ......
    //Getter and Setters

}

对于不同的ValuationAlgorithm,这些属性的内容可能不同。例如,如果算法是A,则yield和probability将包含计算值,其余的将为null;如果算法是B,则standardDeviation和curve将包含结果,其余的将为null等。规则非常复杂,例如,如果approcimateValue为true,则某些值将被覆盖等。因此,所有这些属性必须属于一个类,因为它们在逻辑上是一个结果。

另一种方法是使用Map

class EquityValuationResult {
    private final String YIELD = "yield";
    private final String CURVE = "curve";
    ........

    private ValuationAlgorithm algorithm;
    private final Map<String, Object> result = new HashMap<String, Object>();

    // Getter and Setters
}

但是,如果我这样做,getter和setter必须将值从Object转换为相应的数据类型。我还必须定义这些常量并将它们用作地图的关键,这看起来太麻烦了。

您认为哪种方式更好?还有其他更好的方法吗?

编辑:忘记提及,由于约束,为每个calculateType创建单独的类不是一个选项。我必须使用一个班级。

3 个答案:

答案 0 :(得分:3)

@Joel发表评论,引发了一个灯泡。 Java 8有一个可选项,仅用于此目的。

要了解如何应用这个例子,你可以在这里阅读它,也许这最有效。

http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html

例如:

import java.util.Optional;

public class Result {
    final CalculationType calculationType;
    private Optional<Integer> yield = Optional.empty();
    private Optional<Double> curve = Optional.empty();
    private Optional<Double>  meanValue = Optional.empty();
    private Optional<Double>  probability = Optional.empty();
    private Optional<Integer>  standardDeviation = Optional.empty();

    public Result(CalculationType calculationType) {
        this.calculationType = calculationType;
    }

    public CalculationType getCalculationType() {
        return calculationType;
    }

    public Optional<Integer> getYield() {
        return yield;
    }

    public Optional<Double> getCurve() {
        return curve;
    }

    public Optional<Double> getMeanValue() {
        return meanValue;
    }

    public Optional<Double> getProbability() {
        return probability;
    }

    public Optional<Integer> getStandardDeviation() {
        return standardDeviation;
    }

}

答案 1 :(得分:1)

也许一个选项是创建一个表示变量名的枚举类:

public enum ResultKey {

    YIELD,
    CURVE,
    MEAN_VALUE,
    ...

    // you can add getValue(Map<ResultKey, Object> map) and
    // setValue(Map<ResultKey, Object> map, Object value) methods

}

然后在你的结果类中有一张地图:

class EquityValuationResult {

    private ValuationAlgorithm algorithm;
    private Map<ResultKey, Object> result = new HashMap<>();

    // Getter and Setters
}

所以它基本上就像你的地图想法,但有一个枚举。

答案 2 :(得分:0)

如果允许您创建帮助器或其他内容,请忘记地图示例。在这个限制下,我可能会将枚举作为帮助器/类型来编写,以识别并可能使用映射器来保存基于类型的顺序。

作为结果类中的辅助方法,可能是:

public double[] getCalcValues(){
    switch (calculationType){
    case A:
        // do something
        return null;
    case B:
        // do something
        return null;
    default:
        throw new RuntimeException("Not Really Possible");
    }
}

由于CaclulationType的枚举类型,这有望成为可能。 例如:

public enum CalculationType {
    A("A"), B("B");

    final String calcType;

    private CalculationType(String calcType) {
        this.calcType = calcType;
    }

  // ... other enum stuff
}

在这种情况下,我可以将枚举最终用于实例化,并使用静态辅助方法进行cal值提取,并故意将getter从主类中删除,除非有人拉出空值即可。如果你不想在其他地方需要的话,我会留下一个enum的getter,如果没有,那么我想我也会把它留下来。

public class Result {
    final CalculationType calculationType;
    private int yield;
    private double curve;
    private double meanValue;
    private double probability;
    private int standardDeviation;

    public Result(CalculationType calculationType) {
        this.calculationType = calculationType;
    }

    public CalculationType getCalculationType() {
        return calculationType;
    }

    public double[] getCalcValues(){
        switch (calculationType){
        case A:
            // do something
            return null;
        case B:
            // do something
            return null;
        default:
            throw new RuntimeException("Not Really Possible");
        }
    }   

    // Only include setters below, force users to use getCalcValues as an extraction class
}