【问题标题】:Elegant alternatives for huge amount of arguments in class constructor [closed]类构造函数中大量参数的优雅替代方案[关闭]
【发布时间】:2011-09-17 18:23:29
【问题描述】:

例如,我有一个构建 GUI 的类,一个处理 GUI 的所有事件的类,以及一个包含受 GUI 对象影响的所有对象(主要是滑块)和 GUI 实例的主类-class 和 event-class。

现在,事件类的构造函数将 GUI 类和每个被 GUI 更改的对象作为参数。这些是相当多的对象,所以我现在有大约 8 个参数并且还在增长。

有没有更优雅的解决方案来解决我的问题,30 个参数根本感觉不对?

ps,我宁愿不合并类,因为这三个类都非常大,并且会使所有内容的可读性降低。

【问题讨论】:

  • 所有参数都属于同一类型吗?如果是,那么您可以获取它们的数组。
  • Hashmap 有用吗?我倾向于像 spring 这样的 xml 配置方法,但这可能不适合你
  • @Zoidberg,这不是让事情变得不必要的复杂吗?
  • 我只是应用了 YUI 中使用的一些策略,他们使用配置对象来初始化可以具有大量参数的类。如果您使用哈希图,它允许您将其接受到一个 init 方法中,该方法可以将值提取出来,键入 caste 它们并将它们放入实例变量中。我认为这不会增加太多复杂性,并且会缩短构造函数的参数计数。

标签: java constructor arguments


【解决方案1】:

在这种情况下,通常会使用具有流畅语法的构建器对象。你改变:

new XYZEvent(a, null, null, b, null, c, d, null, null)

new XYZEventBuilder().setA(a).setB(b).setC(c).setD(d).build()

【讨论】:

  • 这种方法有什么好处?
  • @dasdasd:在普通函数或构造函数调用中,参数仅按位置区分。使用流利的语法,参数按名称赋予含义,并且允许顺序变化。 builder 对象还允许将参数列表分段收集,你可以将它保存在一个变量中,设置一些属性,去解析一个文件,设置更多属性,然后最后调用build()
  • 我绝对可以看到这样做的好处,但是在谷歌上搜索了一下后,我找不到这种策略/对象的任何示例(在 java 中)。我应该寻找任何关键字吗?
  • 哦,nvm,我发现了一些东西。感谢您的建议!
  • @Dasdasd:构建器对象和@Alp后来的答案之间的唯一区别是对象的最终构造方式。在我看来,最后一行是GUI myGUI = guiConfig.build();。流畅的语法与使用构建器类是一个单独的问题,@Alp 的配置对象也将从使用它中受益。
【解决方案2】:

您可以创建一个配置类来保存所有参数的默认值:

public class GUIConfig {

  private String name = "default";
  // more private declarations

  public GUIConfig() {
    // constructor, just for setting defaults
  }

  // getters and setters

}

现在您可以像这样简单地创建您的 GUI 类实例:

GUIConfig guiConfig = new GUIConfig();
guiConfig.setName("foo");
// more setters
GUI myGUI = new GUI(guiConfig);

或仅使用默认值:

GUI myGUI = new GUI(new GUIConfig());

【讨论】:

  • 嗯,这确实是一个不错/简单的解决方案。谢谢!
  • 您可以通过将设置器设置为最后的return this; 来启用流畅的语法。然后你可以写:GUI myGUI = new GUI(new GUIConfig().setName("foo"));,如果你愿意的话。或者只是guiConfig.setName("foo").setAddress("123 Bar Road").setCity("Fooville");
【解决方案3】:

使用 DTO (Data Transfer Object) 来举办所有课程。然后可以在单个参数中传递它。

DTO 没有任何行为 除了存储和检索 自己的数据

【讨论】:

    【解决方案4】:

    您应该考虑使用 Google 的 AutoValue 库:https://github.com/google/auto/blob/master/value/userguide/index.md

    @AutoValue
    public abstract class Card {
        @Nullable 
        public abstract Integer localId();
    
        public abstract Long utcStart();
    
        public abstract Integer paramA();
    
        public abstract Integer paramB();
    
        @Nullable 
        public abstract Boolean paramC();
    
        public static Builder builder() {
            return new AutoValue_Card.Builder();
        }
    
        @AutoValue.Builder
        public abstract static class Builder {
            public abstract Builder setLocalId(final Integer localId);
            public abstract Builder setUtcStart(final Long utcStart);
            public abstract Builder setParamA(final Integer paramA);
            public abstract Builder setParamB(final Integer paramB);
            public abstract Builder setParamC(final Boolean paramC);
            public abstract Card build();
        }
    }
    

    所有非必填字段都可以用@Nullable注解。

    要创建不可变的 Card 对象,您只需使用以下代码:

    Card myCard = Card.builder()
                    .setLocalId(123456)  // this line can be omitted
                    .setUtcStart(158632478000)
                    .setParamA(5)
                    .setParamB(58)
                    .setParamC(true) // this line can be omitted
                    .build();
    

    “AutoValue 是一个很好的工具,可以消除用 Java 编写平凡的值类的苦差事。它封装了 Effective Java 第 2 章中的大部分建议,让您可以专注于程序中更有趣的方面。生成的程序可能会更短、更清晰、更无错误。请竖起大拇指。”

    -- Joshua Bloch,作者,Effective Java

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-22
      • 1970-01-01
      • 2011-05-23
      • 2013-08-26
      • 1970-01-01
      相关资源
      最近更新 更多