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と実装を混在させることは、SeparationImplがAPIを実装する方法に固有の何かをAPIに公開することを意味します。

例として、さまざまなコレクションクラスで反復がどのように実装されているかを見てください。特定のコレクション内の要素を取得するためのより具体的な方法がありますが(たとえば、ArrayList内の位置によって)Collection、具体的なArrayListの実装方法に固有であるため、それらは公開されません。

また、インターフェイスの巨大なディレクトリを持つプロジェクトも見ました。各プロジェクトには単一の具体的な実装があり、それぞれが具体的な実装のすべてのメソッドを機械的に再現します。これは、実際には提供されていないため、完全に無意味な「ふり」の抽象化のようです。論理的な抽象化。

于 2011-05-22T19:00:31.903 に答える
4

OSGiでよく使用される手法の1つは、実装とは別のモジュールにAPIを含めることです。APIは、実装への直接の参照を避けて、それ自体でコンパイルする必要があります。

于 2011-05-22T19:00:10.637 に答える
2

PeterとSteveの答えで十分ですが、さらに追加したいと思います。インターフェイスまたは抽象クラスの実装が1つしかない場合は、抽象化の目的に反するため、インターフェイスまたは抽象クラスを使用しても意味がありません。
あなたの場合、私は本当に理解していませんでした-なぜSeparation抽象クラスとして実装したのか、SeparationImplそれ自体がAPIクラスである可能性があります。または、異なる実装Separationがある場合はインターフェースであり、いくつかの共通の機能がある場合は、別の抽象クラスで実装することができます。インターフェイスをSeparationImpl作成し、その抽象クラスから継承します。サンプルクラス階層は次のようになります

interface Separation --> AbstractSeparation --> SeparationImpl 

標準のコレクションライブラリと同じように

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

他の著者からの良い点に加えて、私はユニットテストの目的に言及します:

クラスの代わりにインターフェースを使用すると、オブジェクトをモックアップするのが非常に簡単になります。

于 2011-05-22T19:23:34.693 に答える