【问题标题】:Passing in a large list of values into a constructor to initialise finals.将大量值传递给构造函数以初始化决赛。
【发布时间】:2012-11-13 21:45:33
【问题描述】:

假设我们有这样的情况:

public class Bar1 {
    public final int VALUE1; 
    public final double VALUE2;
    public final String NAME; 
    /*DOZENS OF FINALS!*/

    public Bar1(int v1, double v2, String name)
    {
        this.VALUE1 = v1; 
        this.VALUE2 = v2;
        this.NAME = name; 
    }

}

public class Foo1
{
    private Bar1 bar1;
    private Bar1 bar2;
    private Bar1 bar3;
    /*Dozens of bars!*/

    public Foo1( //We need to pass the values in here)
                 {
                     bar1 = new Bar1( //we need to initialise each of the bars. )
                     bar2 =...
                     bar3 = ...
                 }


}

这样做的好方法是什么?我认为将每一个都作为自己的论点传递,

例如:

public class Foo1
{
    private Bar1 bar1;
    private Bar1 bar2;
    private Bar1 bar3;
    /*Dozens of bars!*/

    public Foo1(int bar1Value1, double bar1Value2, String bar1String, 
                        int bar2Value1, double bar2Value2, String bar2String,
                        int bar3Value1, double bar3Value2, String bar3String)
                 {
                     bar1 = new Bar1(bar1Value1, bar1Value2, bar1String);
                     bar2 = new Bar1(bar2Value1, bar2Value2, bar2String);
                     bar3 = new Bar1(bar3Value1, bar3Value2, bar3String);
                 }


}

真是让人头疼。

我将发布我提出的解决方案,但我想知道还有哪些其他解决方案。

【问题讨论】:

  • 只是不要让它们成为最终的,而是使用构建器。
  • 你考虑过建造者模式吗? (Ps 这不是一个测验网站 - 您应该提供所有相关信息)。
  • @Adam:为什么不让它们成为最终版本?构建器对于构建具有最终字段的不可变对象非常有用。
  • @Adam Builder 模式可以与 final 字段共存。
  • @assylias 我认为决赛必须在构造函数完成的时间进行初始化......显然可以通过使对象不可变、私有构造函数等来模拟决赛。

标签: java constructor initialization final


【解决方案1】:

分离出你的类型。如果您有 几十个 字段,则几乎可以肯定:

  • 其中一些字段相互关联,因此应以它们自己的类型捕获,例如如果您有字段address1address2address3citystate,那么应该是Address 类型

  • 有些字段根本不相关,一开始就不应该属于同一类型

我从未见过一个设计精良的类有几十个字段。

一旦你减少了字段的数量,你就不会对笨重的构造函数有任何问题。

如果您确实仍然有很多字段,那么构建器模式(如 cmets 中提到的)确实不错,如果有点乏味:有一个可变构建器类型(通常是嵌套类型),然后是 build() 方法,它将构建器本身传递给不可变类型的构造器,它将构建器中的值复制到最终字段中。

【讨论】:

  • 问题是争论仍然加起来。我将使用我实际尝试执行的代码进行解释:我有一个 Parameter 类(条形),它具有 MIN MAX DEFAULTNAME。然后我有一个不同数量的参数(一个foo),例如OscillatorFrequencyPhaseAmpFourierCurveSlopeWidth .我不想将最终结果存储在Oscillator 类中,因为我实际上不确定频率的最大值应该是多少。这应该由使用它的应用程序确定。
  • @user1068446:这不是一个非常清楚的解释 - 哪个 final 你不想存储?你绝对不应该有 frequencyMin、frequencyMax、frequencyDefault、frequencyName 等。听起来Oscillator 可以有六个字段,但这还不错......
  • MIN, MAX, DEFAULT, NAME 都是Parameter 类的final。 - 你得到一个单一的振荡器 - 我需要在某个地方输入 6*4 = 24 个值,对吧?问题是 - 我如何轻松地告诉振荡器它的每个参数的 MIN 和 MAX 等值是多少?
  • 这里的元问题:我是否应该编辑我的问题以包含我正在使用的实际代码?
  • @user1068446:您传入 6 个 Parameter 值,这些值是您单独构建的。这才是重点。与其在一个巨大的调用中传递 24 个参数,不如将其分解。
【解决方案2】:

我的解决方案。将值作为二维字符串数组传递,并将每个字符串转换为其对应的类型。

public class Foo1
{
    private Bar1 bar1;
    private Bar1 bar2;
    private Bar1 bar3;

    public Foo1(String[][] values)
    {
        Bar1[] bars = {bar1, bar2, bar3};

        for (int i = 0; i<3; i++)
        {
            bars[i] = new Bar1(Integer.parseInt(values[i][0]), Double.parseDouble(values[i][1]), values[i][2]); 

        }


    }

}




public class FooBar1 {

    private static final String[][] myFoo1Values = {
            //Value1, Value2, Name
            //Integer, Double, String
            {"1", "2.22", "bar 1"},
            {"2", "5.59", "BAR TWO"},
            {"333", "2", "- tre"}
    };

    static private Foo1 myFoo1; 

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        myFoo1 = new Foo1(myFoo1Values);

    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-13
    • 2021-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多