5

サービス(インターフェース)の実装(具象クラス)をAPIユーザーから隠したい。実装は、Java API ServiceLoaderメカニズムを使用するファクトリによってユーザーに提供されます。このローダーでは、実装クラスが公開されている必要があります。ユーザーが直接依存していない別の JAR (API JAR を除く) に実装が隠されている限り、これは問題ありません。

ただし、簡単に配布できるように、デフォルト実装の JAR のコンテンツは API JAR にパックされています。したがって、ユーザーは、デフォルトの実装クラスが公開されているこの事前パックされた JAR に事実上依存しています。人々が実装を直接インスタンス化することを妨げるものは何もありません。私はそれを可能にしたくありません。

私の悪い考え:

  • パッケージのプライベート実装をロードできる ServiceLoader の独自のバージョンを実装します (ところで、なぜ Java API ServiceLoader はこれを許可しないのですか?)
  • 別の API と実装 JAR を出荷する

正しい方法は何だと思いますか?妥協はありますか?

OSGi やその他の重機を使用することは論外です。

4

4 に答える 4

3

残念かもしれませんが:

  • 別の瓶を作り、それを他のサードパーティの瓶と一緒に置きます.
  • インストーラー/展開プロセスですべての適切なパッケージ化を処理します。
  • コンパイル時にこの jar を使用可能にしないでください。メイヴン: <scope>runtime</scope>.

他の唯一の方法は@Deprecated、Java サービス API を使用して対応するクラスを使用する方法をコメントとして javadoc に記載することです。

于 2013-05-08T12:24:52.247 に答える
1

C# では、関連するフレンド アセンブリにのみ表示される内部インターフェイスを作成し、そのインターフェイスを明示的に実装できます。Java でこれを行う方法はわかりませんが、概念的には、これが .NET の世界でこの問題を回避できた方法です。

EDIT Javaにはインターフェイスの明示的な実装がないことがわかります。参考までに、インターフェイスの明示的な実装では、インターフェイス メンバーを介して関数呼び出しを行う必要があります。実装クラスのメンバーとして呼び出すことはできません。これが、少なくとも .NET の世界では、私の手法がうまく機能する理由です。

または、インターフェイスを別の JAR に配置し、API で配布しないことをお勧めします。

于 2013-05-08T13:28:42.650 に答える
0

You can't easily prevent people from instantiating/accessing any shipped class.

As such I would perhaps simply wrap the ServiceLoader mechanism that you're using and provide the instantiated class referenced through a Java interface (rather than as a concrete implementation reference).

于 2013-05-08T10:01:13.477 に答える
0

実装クラス パッケージをプライベートにし、ServiceLoctor を使用して特定のサービスを取得する最初のアプローチを好みます。私のプロジェクトでは、パッケージ構造は次のようになります。

-package
   |-ServiceInterface(public)
   |-ServiceImplementation(default,package private)
   |-ServiceLocator(public)

serviceLocator は次のようになります。

public class ServiceLocator{
    private static final Map<String,Service> services;

    static {
         services=new HashMap<String,Service>();
         services.put("default",new ServiceImplementation());//hide implementation
    }
    public Service getService(String name){
         return services.get(name);
    } 

    public registerService(Service service, String name){
         services.put(name,service)
    }
}

エンド ユーザーは実装クラスにアクセスできず、後で別の実装クラスを使用するように簡単に変更できます。

于 2013-05-08T12:45:40.473 に答える