7

在大型软件实现中,通常建议将 API 设计与其实现分开。但是在某个地方,它们必须重新连接(即,必须将实现重新连接到 API)。

以下示例显示了 API 设计和通过 INSTANCE 对象对其实现的调用:

import java.util.List;

public abstract class Separation {

    public static final Separation INSTANCE = new SeparationImpl();

    // Defining a special list
    public static interface MySpecialList<T> extends List<T> {
        void specialAdd(T item);
    }

    // Creation of a special list
    public abstract <T> MySpecialList<T> newSpecialList(Class<T> c);

    // Merging of a special list
    public abstract <T> MySpecialList<? extends T> specialMerge(
        MySpecialList<? super T> a, MySpecialList<? super T> b);

    // Implementation of separation
    public static class SeparationImpl extends Separation {

        @Override
        public <T> MySpecialList<T> newSpecialList(Class<T> c) {
            return ...;
        }

        @Override
        public <T> MySpecialList<? extends T> specialMerge(
            MySpecialList<? super T> a, MySpecialList<? super T> b) {
            return ...;
        }

    }

}

有些人会争辩说 API 不应该引用实现代码。即使我们通过单独的文件将 API 代码与实现分开,也经常需要在 API 中导入实现代码(至少是类名)。

有一些技术可以通过使用完全限定名称的字符串表示来避免此类引用。该类使用该字符串加载,然后实例化。它使代码更加复杂。

我的问题:将 API 代码与实现代码完全分离或隔离有什么好处?或者这只是纯粹主义者试图达到完美而没有什么实际好处?

4

4 回答 4

6

我一直理解将接口与实现分开的要求意味着您不要将实现的方式什么混合在一起。因此,在您上面的示例中,将 api 和实现混合意味着在 api 中公开特定于 SeparationImpl 如何实现您的 api 的内容。

作为一个例子,看看迭代是如何在各种集合类中实现的。有更具体的方法可以检索特定集合中的元素(例如,通过 ArrayList 中的位置),但这些方法并未公开,Collection因为它们特定于具体 ArrayList 的实现方式。

我还看到有大量接口目录的项目,每个都有一个具体的实现,每个都机械地复制其具体实现中的每个方法,这似乎是一个完全没有意义的“假装”抽象,因为它实际上并没有提供任何逻辑抽象。

于 2011-05-22T19:00:31.903 回答
4

在 OSGi 中经常使用的一种技术是将 API 放在与实现不同的模块中。API 应自行编译,避免直接引用任何实现。

于 2011-05-22T19:00:10.637 回答
2

Peter's and Steve's answers are enough but I would like to add more - if you ever have only single implementation of the interface or abstract class, then its pointless to have interface or abstract class as its defeats the purpose of abstraction.
In your case I really didn't understand - why you implemented Separation as a abstract class, rather SeparationImpl itself can be API class or if you have different implementations Separation can be an inetrface and if you have some common functionality then you can have another abstract class implementing your interface and then SeparationImpl inheriting from that abstract class. the sample class hierarchy would look like

interface Separation --> AbstractSeparation --> SeparationImpl 

just like the standard collection library

interface List --> AbstractList --> ArrayList
于 2011-05-22T19:09:38.383 回答
2

除了其他作者的优点之外,我还要提到单元测试的目的:

当使用接口而不是类时,模拟对象要容易得多。

于 2011-05-22T19:23:34.693 回答