【问题标题】:Design Pattern to replace a method with many parameters [duplicate]用许多参数替换方法的设计模式[重复]
【发布时间】:2014-01-27 08:29:58
【问题描述】:

Java 1.6

我有一个带有很多参数的方法。这不是构造函数,而是普通方法。

 class A {
   public void m (int a, int b, boolean c, List<>...) { }
 }

如何将方法替换为更好的形式?据我了解,Builder 设计模式适用于构造函数。

【问题讨论】:

  • (虽然令人沮丧的是,接受的答案谈到使用构建器模式作为方法,但没有解释如何)
  • 很可能他想引入一种新类型来保存参数,并且该类型(实例)应该是“构建的”并作为单个参数传递给方法。
  • 我认为builder对于这种情况来说太过分了......

标签: java design-patterns builder


【解决方案1】:

如果我遇到一个参数太多的方法,我通常会执行以下步骤:

  1. 我尝试识别与这些参数相关的实体,并检查是否可以使用 Preserve Whole Object 重构。

    您从一个对象中获取多个值,并将这些值作为参数传递给方法调用。 改为发送整个对象。

  2. 如果所有这些参数都是独立的,并且我想增加参数的数量,我会使用另一种常见的解决方案 - Introduce Parameter Object 重构。

    您有一组自然而然地结合在一起的参数。 用一个对象替换它们。

    为了构建object,可以使用其他技术和模式(例如生成器、方法链、Fluent 接口)。

【讨论】:

    【解决方案2】:

    如果参数自然组合在一起,它们可以替换为Parameter Object。如果您不想在 Parameter Object 的构造函数中列出一长串参数,您可以使用 Builder 设计模式来构造它。另一个有点相关的技术是Preserve Whole Object

    【讨论】:

      【解决方案3】:

      您对 Builder 的看法是正确的,这取决于这些参数是否是强制性的。

      我个人会从http://en.wikipedia.org/wiki/Single_responsibility_principle 开始,因为带有许多参数的方法(以及构造函数或类)有异味。我的意思是,这些参数是否相关,方法逻辑是否相关?有意义吗?

      如果这些参数有一些关系,它们可以适合某种领域实体。

      【讨论】:

        【解决方案4】:

        Builder模式用于逐步构造一个复杂的对象,最后一步将返回该对象。构造对象的过程应该是通用的,以便它可以用于创建同一对象的不同表示。

        “将复杂对象的构造与其表示分离,以便相同的构造过程可以创建不同的表示”

        【讨论】:

        • 是的,你是对的。但什么是解决方案?
        • 根据逻辑将方法划分为更细粒度的方法,这也减少了方法中的参数数量,最终使用构建器模式得到结果。这种方法有两个好处 1) 参数的数量会减少 2) 程序变得更加模块化。
        • Builder 很棒,但需要大量代码。在只有一种方法的情况下,这种模式是多余的。应该有一个原因,比如 Hibernate 标准。
        【解决方案5】:

        如果参数个数是动态的,可以使用double brace initialization:

        public static void main(final String[] args) {
            method(new HashMap<String, Object>(){{
                put("p1", new Object());
                put("p2", new Object());
            }});
        }
        
        private static void method(Map<String, Object> params){
        
        }
        

        它有一些缺点,但仍然可行。小心每个呼叫站点都有自己的匿名类。类型安全也可能存在一些问题。您可以使用枚举代替基于字符串的键。可以使用任何自定义类型代替 Map,Map just 是最常见的。在动态参数长度的情况下,DBI 比可变参数更有用。

        【讨论】:

        • 例如,@atamanroman 您应该向 Groovy 开发人员报告您的疑虑。或任何其他基于 JVM 的脚本语言开发人员。他们会很高兴的。 JLS 完全支持这种方法,所以它不是黑客攻击。
        • 谢谢。一个有趣的建议。我没有动态参数,但感谢任何帮助
        • @Mikhail 这与除 java 之外的任何其他 jvm 语言无关。在 java 中,双括号初始化是一种不太为人所知的语法技巧,具有严重的缺陷、性能影响和零优势。
        【解决方案6】:

        如果你需要很多参数 - 出了点问题......

        method not static -> 您可以将一些参数定义为字段。

        如果你真的需要这样做,也许最好创建类 A.AMParameter(int a, int b, boolean c, List...),并将它传递给 m (A.AMParameter),或者使用地图...

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-08-23
          • 2021-10-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多