2011-12-10 4 views
1

私はクラスがたくさんありますUNO、HAV、MAS、KOS 私は工場パターンを作成したいと思います。Javaファクトリパターン - クラスを動的にロードする

validator.load("UNO").validate(); 

私はバリデータクラスにクラスをロードしてインスタンスを返す動的にする必要があります。
(クラスの名前を動的に設定してインスタンスを返す)
私の問題は、互換性のない型がある場合、クラスのインスタンスを返すにはどうすればいいですか?

返品タイプのメソッドに何を書き込むのか分かりません。

バリデーションクラスの主な問題

public SegmentAbstract load(String str) { 

return SegmentAbsClass.forName(identify); 

メインクラス

try{ 
    validator.load("UNO").validate(); 
}catch(Exception e){ 
    System.out.print("No class "); 
} 

抽象クラス(SegmentAbstract)

public abstract class SegmentAbstract { 

    public abstract Boolean validate(); 
} 

クラスUNO

public class UNA extends SegmentAbstract{ 

    public Boolean validate() { 
    System.out.print("UNO!!"); 
    return true; 
    } 

} 

クラスバリ

public class Validator { 

    public SegmentAbstract load(String str) { 
    String identify = str.substring(0, 3); 
    try { 

     return SegmentAbsClass.forName(identify); 
    } 
    catch(Exception e) { 
     return this; 
    } 

    } 
} 
+0

いつも 'SegmentAbstract'クラスの新しいコピーを返さなければなりませんか? – hellectronic

+1

@Dezigoあなたのクラスが 'SegementAbstract'を拡張している限り、それらはすべて' validate() 'を実装するので互換性がありません。何が問題なのですか? – stacker

+0

はい!常に新しいコピー! – Dezigo

答えて

1

は、私はそのような何かをします。

// ISegment.java 
public interface ISegment { 
    Boolean validate(); 
} 

// Uno.java 
public class Uno implements ISegment { 
    public Boolean validate() { 
     System.out.print("UNO!!"); 
     return true; 
    } 
} 

// SegmentFactory.java 
public final class SegmentFactory { 
    public static enum Supported { 
     UNO("uno", Uno.class), /* ... */, HAV("hav", Hav.class); 

     private final Class<?> clazz; 
     private final String name; 

     private Supported(final String name, final Class<?> clazz) { 
      this.name = name; 
      this.clazz = clazz; 
     } 

     public Class<?> getClazz() { 
      return clazz; 
     } 

     public static Supported for(final String name) { 
      for (final Supported s : values()) { 
       if (s.name.equals(name) { 
        return s; 
       } 
      } 
      return null; // a default one 
     } 
    } 

    public static ISegment create(final Supported supp) { 
     if (supp == null) { 
      return null; 
     } 
     return supp.getClazz.newInstance(); 
    } 

    private SegmentFactory() { 
     // avoid instantiation 
    } 
} 

用法:

final ISegment sa = SegmentFactory.create(SegmentFactory.Supported.for("uno")); 
sa.validate(); 

テストされていません!

2

このお試しください:多分これが役立つ???

public interface Validator { 
    boolean validate(Object obj); 
} 

public final class ValidatorFactory { 
    private ValidatorFactory(){} 

    public static Validator load(String type){ 
     try { 
      Class<?> clazz = Class.forName(type); 
      if (Arrays.asList(clazz.getInterfaces()).contains(Validator.class)){ 
       return (Validator) clazz.newInstance(); 
      } 
      throw new IllegalArgumentException("Provided class doesn't implement Validator interface"); 
     } catch (Exception e) { 
      throw new IllegalArgumentException("Wrong class provided", e); 
     } 
    } 
} 

+0

ありがとうございますが、私は別の方法を選択しました:) – Dezigo

1

hereをご覧ください。簡単に言うと、ファクトリクラス(Map<String,String>、キーは識別子、値は完全修飾クラス名)でマップを作成し、初期化時にサポートされているクラスを追加することです。次に、リフレクションを使用してファクトリメソッドでオブジェクトをインスタンス化します。また、Map<String,String>の代わりにMap<String, SegmentAbstract>を使用し、SegmentAbstractクラスにpublic abstract getNewSegment()を追加することで、反射を避けることができます。

+0

リファクタリングのために 'Map >'を使う方が良いと思います。 –

+0

@RC:これはうまくいけばOPが正しい方向に押し上げられていることに同意します。 – a1ex07