如何处理构造函数中的过多参数?

时间:2013-06-03 16:37:20

标签: java constructor

我正在制作一个应用程序,这个应用程序本应是我的个人宠物项目,旨在通过我玩的电脑游戏比较两辆车与另一辆车 车辆有一大堆的统计信息,如速度,healthpoints,炮塔遍历等等,我想创建一个小的应用程序,将突出车辆之间的差异,但是我已经来到了一个绊脚石,其中采取的构造函数的参数每辆车都很庞大,难以阅读

以下是使用给定构造函数创建对象的示例:

HeavyTank T110E5 = new HeavyTank("T110E5", 2200,54.56d, 875, 37, 30, 254,76,38, 203,127,70,300, 202, 6,32, 400,745,10);

我相信你会猜到,这个应用程序我提出,是基于关闭坦克,在那里我硬编码的坦克统计的世界坦克比较器,但正如你所看到的,所采取的论点是难以阅读,使很难创建新对象而不会感到困惑。每个坦克都有不同的统计数据,这意味着我必须单独硬编码接近100多个坦克。如果这里有人有减少混乱的解决方案,或者我愿意倾听的建议。

我也想恢复的问题,我在上面做了,这个应用程序是不是出于商业目的,纯粹只是我的宠物的个人项目。

9 个答案:

答案 0 :(得分:3)

我建议以简单的文件格式存储您的坦克数据,例如每个坦克一行的CSV文件。然后你的坦克对象可以采用类似InputStream的参数作为参数,然后从文件中输入坦克细节。

如果你使用CSV文件,你可以使用一个典型的电子表格程序来轻松编辑你的坦克细节。

答案 1 :(得分:2)

这听起来像是builder pattern的完美用例。

lots of good examples如何实现此目标。以下是Google在the CacheBuilder class of Guava中使用它的方式:

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
   .maximumSize(10000)
   .expireAfterWrite(10, TimeUnit.MINUTES)
   .removalListener(MY_LISTENER)
   .build(
       new CacheLoader<Key, Graph>() {
         public Graph load(Key key) throws AnyException {
           return createExpensiveGraph(key);
         }
       });

此特定示例甚至使用method chaining,但这不太重要。主要功能是newBuilder()设置了一些默认参数,然后您可以通过一个或多个方法调用选择性地进行调整。最后,调用build()来实际创建实例(并使用长参数列表调用实际的构造函数)。

答案 2 :(得分:0)

JavaDoc +优秀的IDE将帮助您确定需要提供的参数。

否则,您可以将参数包装在单个对象中并将其传递给构造函数。重载的构造函数可以正常工作,因为您可以解压缩参数并将其传递给原始参数。

如果您事先知道参数,则始终将它们放在属性文件中并使用java.util.Properties读取它们。

答案 3 :(得分:0)

使用fluent interface。虽然通常在ccnstructor之外使用,但为什么不在部分内部使用。

答案 4 :(得分:0)

您可以考虑将该信息放在可以轻松编辑的属性文件中。然后,您的构造函数将获取属性文件的名称,并具有强制完整性和验证的附加任务。虽然我仍然喜欢强类型构造函数,但从长远来看,属性文件方法可能更容易使用。

答案 5 :(得分:0)

如果混合使用必需参数和可选参数(具有合理的默认值),则可以使用构建器模式。 Effective Java的一个例子:

public class NutritionalFacts {
    private int sodium;
    private int fat;
    private int carbo;

    public static class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder(int s) {
            this.sodium = s;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

然后你可以做以下事情:

NutritionFacts cocaCola =  new NutritionFacts.Builder(240, 8). calories(100).sodium(35).carbohydrate(27).build();

前两个参数是必需的(240和8)。其他属性是可选的,可以通过适当命名的方法提供。

如果您有大量必需参数,您仍然可以使用构建器模式;您可以检查它们是否已在build()方法中设置。

答案 6 :(得分:0)

我建议实现不带任何参数的标准构造函数。可以通过eclipse生成Setters和Getters。这有助于全面了解并添加或删除成员。 接下来你应该做的是将所有车辆内容写入XML文件中。标签可以帮助您了解车辆名称,数值等。添加和移除车辆也会更容易。 您可以通过JDOM访问XML文件。只需读取车辆标签,并使用XML文件中的值调用setter方法。这可以通过循环来完成。

最后,您唯一需要注意的是车辆XML文件。

随时询问是否有任何问题。

答案 7 :(得分:0)

我看到你有三个合理的选择:

1)使用标准contructor("string", value, "string", value,...)格式。     这可能比您想要投入到该计划中的努力更多。

2)对每个属性使用constructor()方法,然后使用setPropertyName(value)方法。     这将允许您轻松添加它们,但您仍需要手动完成。

3)从文件中读取数据。     使用带有名称的列设置文件(以避免将“我忘记了下一个值”问题移到另一个地方)这应该是最好的。

答案 8 :(得分:0)

我的建议是在初始化时创建一个对象来保存这些类型和特定的参数列表。您可以根据逻辑上的类型划分该对象。然后你只需要两个或三个构造函数,每个构造函数有五个参数。例如:

HeavyTank T110E5 = new HeavyTank("T110E5", 2200,54.56d, 875, 37, 30, 254,76,38, 203,127,70,300, 202, 6,32, 400,745,10);

会变成:

StatObject1 stat1 = new StatObject1(2200, 54.56d);
StatObject2 stat2 = new StatObject2(875, 37, 30);
StatObject3 stat3 = new StatObject3(254, 76, 38);
...
HeavyTank T110E5 = new HeavyTank("T110E5", stat1, stat2, stat3, ...);

或者对您的系统逻辑上有效。这样做的好处是你可以将它应用于你创建的任何其他坦克,并且可以在特定于该数据的每个StatObject类中创建修饰符。