0

まず、質問の仕方がわからないので、より良いタイトルの提案があれば教えてください。

他の人が実装を追加できるようにインターフェイスを作成し、実行時にどの実装を使用するかを決定したいと考えています。

つまり、「Food」インターフェースを作成し、「Breakfast」と「Lunch」の 2 つの実装が存在します。実装では、両方とも同じメソッド名と同じ引数を持っています。実行時にユーザーがどちらかを呼び出せるようにしたいと考えています。「朝食を使用するmakeFood()」または「昼食を使用するmakeFood()」。

1 つの可能性は、1 つの実装のみをコンパイルすることですが、将来別の実装を使用する必要がある場合は、.class ファイルを削除する必要があります。

または、ある種の継承を使用する必要がありますか?

さらに(優先度ではありません):実装クラス名がわからないので、誰かが「ディナー」または「セカンドブレックファースト」を作成できます。これは、ユーザーがまだ実装されていない「クラス」を要求した場合にどうするかという別のジレンマに私を導きます:SIは、ユーザーがどの実装が利用可能かを常に知っていると想定できます。

4

3 に答える 3

5

これは、戦略パターンがニーズに合っているように思えます (GOF - http://en.wikipedia.org/wiki/Strategy_pattern )。

これをどれだけダイナミックにしたいかはわかりません。インターフェイスの 2 つの実装と、どちらかを選択するセレクター メソッドを用意するのが最も簡単です。しかし、インターフェイスの実装をその場で動的に生成するところまで行くこともできます。いずれにせよ、戦略パターンはこの種の複雑さを抽象化し、必要なランタイム基準に基づいてさまざまな動作を選択できるようにします。

クラスを動的にロードする例を次に示します。完全修飾クラス名がすでにわかっていて、オブジェクトに引数なしのコンストラクタがあると仮定します。

Class c = Class.forName("java.lang.Object");
Object o = c.newInstance();

System.out.println( "o = " + o );

この場合にキャッチする必要があるエラーは、InterruptedException、ClassNotFoundException、IllegalAccessException、InstantiationException です。かなりの数ですが、それらをすべて同じ方法で処理し、ユーザーの選択を拒否します。

引数付きのコンストラクターが必要な場合は、次のようにします。

Class c = Class.forName("java.lang.String");
Constructor cons = c.getConstructor( String.class ); // the args here are the expected types for the constructor that you require on the class
String s = (String) cons.newInstance( "hello" );

これにより、キャッチする必要がある例外がさらに追加されます: InterruptedException、ClassNotFoundException、IllegalAccessException、InstantiationException、NoSuchMethodException、InvocationTargetException。ただし、以前と同じ方法でユーザーの選択を拒否します。

于 2013-04-12T07:59:07.693 に答える
1

クラス名がわからず、使用可能なすべてのクラスを知りたい場合は、実行時にインターフェイスのすべての実装を取得する必要があります。これは Reflections で実現できます: http://code.google.com/p/reflections/

メソッドをご覧くださいgetSubTypesOf

ユーザーに独自の実装を提供してこれを使用してもらいたい場合は、さまざまなオプションがあります。

1) 起動時に提供された Jar を読み取り、事前に構成されたセットアップ (Spring など) で依存性注入を使用します。ユーザーは、アプリケーションが開始される前に、完全に修飾されたクラス名をセットアップに書き込むことができます。

2) ServiceLoader のようなプラグイン メカニズムを使用する: http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.htmlまたは JSPF : http://code.google.com/p /jspf/ .

または、実行時に新しい実装を読みたい場合は、OSGi を使用できます: http://en.wikipedia.org/wiki/OSGi (Apache Karaf、Eclipse Equinox、および Apache Felix をご覧ください)。

于 2013-04-12T08:37:39.150 に答える
0

Java のinterface. 例えば:

Food.java:

interface Food {
    void makeFood();
}

朝食。Java:

class Breakfast implements Food {
    void makeFood() { System.out.println("Breakfast."); }
}

ランチ.java:

class Lunch implements Food {
    void makeFood() { System.out.println("Lunch."); }
}

あなたが言ったように、ここには の2つの異なる実装がありFoodます。Foodこれで、実装クラスのいずれかを構築することにより、オブジェクトをインスタンス化できます。

Food myFood = new Breakfast();

また

Food myFood = new Lunch();

ファイルの削除などはありません。物事がより明確になることを願っています。

于 2013-04-12T07:59:59.640 に答える