1

パラメータ化された型としてインターフェイスを使用し、この特定のインターフェイスの実装クラスを返す静的ファクトリ メソッド/クラスを Java で作成することは可能ですか?

ジェネリックに関する私の知識は限られていますが、私がやりたいことは次のとおりです。

// define a base interface:
public interface Tool {
    // nothing here, just the interface.
}

// define a parser tool:
public interface Parser extends Tool {
    public ParseObject parse(InputStream is); 
}

// define a converter tool:
public interface Converter extends Tool {
    public ConvertObject convert(InputStream is, OutputStream os);
}

// define a factory class
public class ToolFactory {
    public static <? extends Tool> getInstance(<? extends Tool> tool) {
       // what I want this method to return is:
       // - ParserImpl class, or
       // - ConverterImpl class
       // according to the specified interface.
       if (tool instanceof Parser) {
          return new ParserImpl();
       }
       if (tool instanceof Converter) {
          return new ConverterImpl();
       }
    }
}

指定したツール インターフェイスから拡張される getInstance() メソッドにインターフェイス「タイプ」のみを挿入するようにクライアント コードを制限したいと考えています。このようにして、挿入されたツールタイプが正当なツールであることを確実に知ることができます。

クライアント コードは次のようになります。

public class App {
   public void main(String[] args) {

      Parser parser = null;
      Converter converter = null;

      // ask for a parser implementation (without knowing the implementing class)
      parser = ToolFactory.getInstance(parser);

      // ask for a converter implementation
      converter = ToolFactory.getInstance(converter);

      parser.parse(...);
      converter.convert(... , ...);
   }
}

ファクトリは、ファクトリから要求される前に定義されたインターフェイスのタイプをオンにする必要があります (null かどうかは気にしないでください)。これが私が書いた方法ではうまくいかないことはわかっていますが、読者の 1 人が私が達成したいことを知っていることを願っています。

getInstance メソッドの戻り値の型は受信パラメーターと同じであるため、Parser インターフェイスが渡されると、Parser p = new ParserImpl(); も返されます。p を返します。

助けてくれてありがとう。

4

1 に答える 1

7

いくつかのこと:

  1. ファクトリは、ツールオブジェクトではなく、ほぼ確実にクラスをインスタンス化する必要があります。aを取得するためにメソッドに渡すa を誰かに作成させるのは、鶏と卵のどちらかです。ParserParser
  2. ワイルドカードであるメソッドに汎用パラメーターを使用できるかどうかはわかりません。これは無意味で無意味なので、そうではないと思います。メソッドをパラメーター化するときは、後で参照できるように、ジェネリック パラメーターに名前を付ける必要があります。

これらをまとめると、ファクトリ メソッドは次のようになります。

public static <T extends Tool> T getInstance(Class<T> toolClass) {
   if (Parser.class.isAssignableFrom(toolClass) {
      return new ParserImpl();
   }
   else if (Converter.class.isAssignableFrom(toolClass) {
      return new ConverterImpl();
   }

   // You'll always need to have a catch-all case else the compiler will complain
   throw new IllegalArgumentException("Unknown class: " + toolClass.getName());
}

の型をインターフェースに制限したい場合toolClass、コンパイル時にこれを行うことはできませんが、もちろんランタイム チェックを導入することはできますtoolClass.isInterface()

ところで、この静的にハードコーディングされた切り替えは、一般的にあまり良くありません。私の考えでは、クラスとコンストラクターの関係を a に入れMap、構築プロセスを動的に検索する方が良いでしょう。値を として保存しCallable<? extends Tool>、保護されたメソッドを追加して、他のクラスがマッピングを登録できるようにすることもできます。

それはあなたの現在のバージョンがうまくいかないということではありません。単にスケールがうまくいかないということです。今のところ、呼び出し元が単にtoolClass.newInstance()自分自身を呼び出すのではなく、別のファクトリを持つことを正当化するために多くのことをしているとは思いません。

于 2010-11-11T11:15:21.933 に答える