【问题标题】:What's a suitable return type for this Java method?此 Java 方法的合适返回类型是什么?
【发布时间】:2011-08-16 08:40:55
【问题描述】:

我们正在实施一个具有策略模式的系统。

某些特定方法的调用者需要数据的 Hashmap,而在某些情况下,它可能是用户定义的 DTO。有些人两者都需要。

我们如何决定使用哪种返回类型,而不是包含 Hashmap 和 DTO 的 Arraylist?还有更合适的吗?

例子:

一些调用者只需要 2 个字符串并且更喜欢 Hashmap。

同一 API 的其他调用者需要 12 个适合放入 DTO 的值。第一个调用者不需要 DTO 中的所有元素。

第三个调用者需要所有 14 个值,因此需要两个结构。

【问题讨论】:

  • 请提供更多上下文。
  • 在什么情况下两者都需要?
  • 您能详细说明不同的情况吗?为什么需要 HashMap 或 DTO?将包含哪些数据?

标签: java


【解决方案1】:

如果一些调用者需要Map(顺便说一句,不要在你的接口中使用像HashMap 这样的具体类型)而其他调用者需要一个对象,那么可能有两个原因:

  • 该方法根据参数返回完全不同的内容(例如,如果设置了标志,则返回权限映射,如果未设置,则返回代表用户本人的对象

  • 您正在返回同一实体的不同视图

在第一种情况下,您的界面存在严重缺陷,应该重新设计。可能您需要两种方法来执行不同的任务。 “不同的调用者”是什么意思?根据谁调用该方法,您决定返回什么?

在第二种情况下,考虑一个更通用的模型并将其返回。然后让客户将其转换为适当的格式。有几种方法可以做到这一点:

  • 返回与格式无关的类型并提供转换为映射和对象的方法,以便客户端可以决定。例如,如果您不确定客户端是否更喜欢具有属性的弱类型映射或具有相同属性/字段的强类型对象,请返回具有 toMaptoObject 方法的简单包装器。请注意,在这种情况下,内部表示并不重要,客户端始终使用视图,您可以随时添加新格式

  • 返回具有两个子类的通用 Model 类:MapModelObjectModel,在子类中公开适当的 getter。 不要使用instanceof,而是使用访客模式。在此模型中,您始终返回单个值,并且客户端必须能够处理每种格式。如果添加新的格式(如XmlModel),所有使用Model的地方都需要自定义处理新的类型。但是在这种情况下,您不需要将内部表示转换为不同的格式

请注意,返回 Object 或其任何变体只是进入动态语言领域,您不再有任何静态类型帮助。

【讨论】:

  • 因此,为了便于阅读,您需要两种方法来执行不同的任务。没有什么可以阻止您在内部重用某些代码,但 API 确实需要两种方法来保持简洁和易于理解。
【解决方案2】:

我将创建一个特定于策略的返回类型类,它封装这两个选项以提供一个清晰的类型化接口,而不是在整个实现代码中杂乱无章地使用 Object instanceof/casts。在我看来,一点点样板是可以接受的:

SomeClass {
    private final Map values;
    private final Object dto;

    SomeClass(Map values, Object dto) {
        ...
    }

    <D> D getDTO(Class<D> dtoType);
    Map getMap();..
}

如果您预先知道 DTO 类型,则返回类型是通用的(您不应该这样做,这意味着您做出了糟糕的设计选择)

【讨论】:

    【解决方案3】:

    使用 getter 和 setter 创建一个数据类并返回相同的 Object..

    【讨论】:

      【解决方案4】:

      你为什么不简单地返回一个对象。理想情况下,我会把它作为最后的选择。但是你也可以考虑返回一个泛型

      public Object myMethod1(){}
      
      public T myMethod2(){}
      

      在第二种情况下,很明显您可能必须定义您的通用对象。

      【讨论】:

        【解决方案5】:

        假设您返回的是泛型类型并且列表可以是异构的,那么返回对 ArrayList 的引用并不是一个坏主意。您可以将所有内容封装在另一个类中,但最后,您需要在某处维护某种列表。

        【讨论】:

          【解决方案6】:

          您可以使用泛型,但问题在于您需要同时返回这两个东西。最好的解决方案是创建一个包含两种返回类型的类,并简单地使用泛型创建一个返回所需内容的方法:

          public <T extends SomeReturnObject> List<T> doSomething(Object someObject, Class<T> classToReturn) {
             // Do something here
          }
          

          【讨论】:

            【解决方案7】:

            如果没有关于您的方法的更多信息,我会尝试使用提供所需方法的接口。然后您可以为HashMap 提供一个包装器,您的DTO 可以直接实现该接口,您还可以拥有一个包含HashMap 和一个DTO 的包装器。

            只要提供了所需的方法,调用者就不应该真正知道返回了什么。

            【讨论】:

              【解决方案8】:

              泛型呢?

              public <T> T getPojo(final Object o, final Class<T> returnType)
              {
                  if (o instanceof HashMap)
                  {
                      return (T) getPojoHash((HashMap) o);
                  }
                  return (T) getPojoDTO((DTO) o);
              }
              
              private HashMap getPojoHash(final HashMap map)
              { // mount map
                  return newMap;
              }
              
              private DTO getPojoDTO(final DTO d)
              { // mount dto
                  return newDTO;
              }
              

              您可以使用反射来避免returnType 参数。但我更喜欢打字。

              【讨论】:

              • 我已更新您的答案,将泛型参数 T 也应用于 Class 参数,从而使该方法更加类型安全且易于使用。
              • 怎么称呼这个方法?
              • 您只需传递哈希或 dto。
              • 所以该方法必须检查传入的类的类型并相应地构建映射或 dto?那是丑陋的。你能展示一下这个方法的实现吗?
              • 无论采用哪种方式实现都在私有中进行。
              【解决方案9】:

              我认为最简单的解决方案是在 Strategy 接口上放置 2 个方法,每个返回类型一个。

              public interface Strategy {
                  Map<String, String> executeReturningMap();
                  DTO executeReturningDTO();
              }
              

              然后调用者可以通过调用适当的方法自己选择他们想要的返回类型。

              没有大惊小怪,只是偏离了策略只能有一种方法的纯粹思想。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2012-10-31
                • 1970-01-01
                • 2020-02-16
                • 1970-01-01
                • 2022-12-12
                • 1970-01-01
                • 2017-08-16
                • 1970-01-01
                相关资源
                最近更新 更多