# API 设计

> 原文： [https://docs.oracle.com/javase/tutorial/collections/interoperability/api-design.html](https://docs.oracle.com/javase/tutorial/collections/interoperability/api-design.html)

在这个简短但重要的部分中，您将学习一些简单的指导原则，使您的 API 能够与遵循这些指南的所有其他 API 无缝地互操作。从本质上讲，这些规则定义了在收藏世界中成为一个好的“公民”需要什么。

## 参数

如果您的 API 包含需要输入集合的方法，那么将相关参数类型声明为集合[接口](../interfaces/index.html)类型之一是至关重要的。 **从不**使用[实现](../implementations/index.html)类型，因为这违背了基于接口的集合框架的目的，即允许在不考虑实现细节的情况下操纵集合。

此外，您应该始终使用最不具体的类型。例如，如果 [`Collection`](../interfaces/collection.html) 可以，则不需要 [`List`](../interfaces/list.html) 或 [`Set`](../interfaces/set.html) 。这不是你不应该在输入上要求`List`或`Set`;如果方法依赖于其中一个接口的属性，则这样做是正确的。例如，Java 平台提供的许多算法都需要输入`List`，因为它们依赖于列表的排序事实。但是，作为一般规则，输入时使用的最佳类型是最常用的：`Collection`和`Map`。

* * *

**Caution:** Never define your own ad hoc `collection` class and require objects of this class on input. By doing this, you'd lose all the [benefits provided by the Java Collections Framework](../intro/index.html).

* * *

## 返回值

使用返回值比使用输入参数更灵活。返回实现或扩展其中一个集合接口的任何类型的对象都可以。这可以是接口之一，也可以是扩展或实现这些接口之一的专用类型。

例如，可以设想一个名为`ImageList`的图像处理包，它返回实现`List`的新类的对象。除了`List`操作之外，`ImageList`还可以支持任何特定于应用程序的操作。例如，它可能提供`indexImage`操作，该操作返回包含`ImageList`中每个图形的缩略图图像的图像。值得注意的是，即使 API 在输出上提供`ImageList`实例，它也应该接受输入上的任意`Collection`（或可能是`List`）实例。

从某种意义上说，返回值应该具有输入参数的相反行为：最好返回最具体的适用集合接口，而不是最常见的。例如，如果您确定始终返回`SortedMap`，则应该为相关方法提供`SortedMap`的返回类型而不是`Map`。 `SortedMap`实例构建比普通`Map`实例更耗时，并且功能更强大。鉴于您的模块已经投入时间来构建`SortedMap`，因此让用户访问其增加的功能是很有意义的。此外，用户将能够将返回的对象传递给需要`SortedMap`的方法，以及接受任何`Map`的方法。

## 旧版 API

目前有很多 API 可以定义自己的临时集合类型。虽然这很不幸，但鉴于 Java 平台的前两个主要版本中没有 Collections Framework，这是生活中的事实。假设您拥有其中一个 API;这是你能做些什么。

如果可能，请改进旧版集合类型以实现其中一个标准集合接口。然后，您返回的所有集合将与其他基于集合的 API 平滑地互操作。如果这是不可能的（例如，因为一个或多个预先存在的类型签名与标准集合接口冲突），请定义一个 _ 适配器类 _，它包装您的一个旧集合对象，允许它作为一个标准集合。 （`Adapter`类是 [_ 自定义实现 _](../custom-implementations/index.html) 的一个例子。）

如果可能，使用遵循输入准则的新调用来改进 API，以接受标准集合接口的对象。此类调用可以与采用旧版集合类型的调用共存。如果这是不可能的，请为遗留类型提供构造函数或静态工厂，该构造函数或静态工厂接受其中一个标准接口的对象，并返回包含相同元素（或映射）的旧集合。这些方法中的任何一种都允许用户将任意集合传递到您的 API 中。