【问题标题】:Exposing Collection or Set for public API公开公共 API 的集合或集合
【发布时间】:2015-02-18 17:15:53
【问题描述】:

据说针对接口而不是特定类型进行编码是一种好习惯。换句话说,我们在创建 API 时公开通用接口而不是特定实现。

例如:

public Collection<Model> getUniqueModels();
public void setUniqueModels(Collection<Model> modelCollection);

但我的问题是,如果我想让消费者知道我只会返回一组独特的模型,即所有模型都会不同,该怎么办。

public Set<Model> getUniqueModels();
public void setUniqueModels(Set<Models> modelSet);

这是创建 publc API 的坏方法吗?如果我使用合集,而消费者发送了一份无效的重复模型列表怎么办?

【问题讨论】:

  • coding against the interface rather than a specific type:Set也是一个接口。如果您期望Set,那么在签名中说Collection 是没有意义的,是吗?
  • 我同意,但请看下面的答案。这就是我的疑问

标签: java collections set public


【解决方案1】:

设计“宽松”公共 API 的一个好方法是,在返回的东西上尽可能具体地类型,在接受的东西上尽可能宽容。

在这种特殊情况下,您应该返回 Set&lt;Model&gt; 并接受 Collection&lt;Model&gt;,并理解任何重复项都将被忽略:

public Set<Model> getUniqueModels();
public void setUniqueModels(Collection<Model> modelSet);

甚至

public void setUniqueModels(Collection<? extends Model> modelSet);

这样的 API 会告诉用户他们不会从 getter 中获取模型之间的任何重复,但它会接受 setter 中其他类型的集合,以防您的 API 的用户更喜欢在其他一些模型中验证唯一性方式(例如,通过使用确保唯一性的查询从数据库中提取 List&lt;Model&gt;)。

如果消费者在不知情的情况下发送了重复列表怎么办?

对此有两种方法:您可以默默地忽略它,或者您可以验证并引发异常。

第一种方法(即忽略重复项)通常足够好:Java API 就是这样做的,例如,当从集合构造 HashSet&lt;T&gt; 时。与其让用户到处制作独特的集合,您可以制作一个独特的集合,然后让他们将副本传递给您。

但是,即使是第二种方法也比接受Set&lt;Model&gt; 为用户提供了更大的灵活性,因为它让用户自行决定是否使集合具有唯一性。

【讨论】:

  • 您的意思是返回 Collection 并接受 Set
  • 我明白你的意思,但我唯一担心的是,如果消费者在不知情的情况下发送了重复列表怎么办?
  • 感谢您的出色解释。如果我采用第一种方法,那不会在消费者不知情的情况下丢失数据吗?我喜欢第二种方法,因为它让 api 告诉消费者如果有重复将引发异常,但仍然可以灵活地接受集合。
  • 嗯没有注意到这一点。非常感谢。您介意在答案中添加倒数第二条评论吗?这将是一个完整的答案。
【解决方案2】:

使用Set接口还是符合对接口编程的原则。只要它定义了您打算使用的集合的语义,它就没有任何问题,在这种情况下,集合中的所有元素都是唯一的。 CollectionSet都是接口,但后者让消费者明白没有重复。

【讨论】:

    【解决方案3】:

    公开Set 接口是可以接受的——毕竟这仍然是一个接口而不是一个具体的类。 公开一个特定的具体类(例如 HashSet)是不好的做法,但你可以公开使用 Set。我认为没有必要只公开最高级别的接口。

    【讨论】:

      猜你喜欢
      • 2010-09-22
      • 2013-12-29
      • 2012-01-26
      • 2010-10-04
      • 2016-10-11
      • 2012-11-07
      • 2018-07-01
      • 1970-01-01
      • 2010-12-05
      相关资源
      最近更新 更多