2009-03-30 12 views
4

こんにちは、私の質問はこれです。コンバータの実装方法を定義するインタフェースがあるとします。このインタフェースは、loadDocument()メソッドと別のconvert()メソッドを持つことができます。 ConvertHTML2DOC、ConvertXML2HTML e.t.cというコンバーターを複数用意したいと考えているとします。前提条件に基づいて新しいインスタンスを作成するための最良の方法

2つの文字列に変換する必要がある2つの形式を取得したとします(どのように取得するかは関係ありません)。これで、コンバータのインスタンスを作成し、ドキュメントを変換する必要があります。

私の質問は、実際には精巧なif文を作成するか、Classクラスのリフレクションを通してクラスをロードする方が良いですか?私が意味することの少しの例を書きました。私の例では、インターフェイスを共有する2つのクラスP1とP2があります。私はまた、スピードの違いを示すためにそれらの50000を作成します。実際の呼び出しは少し速くなっていますが、最初に述べたような複雑な例では、Classメソッドを使用してクラスを作成する利点がより便利でメンテナンス性に優れていると思います。あなたの考えは?

import java.util.*; 

public class Test { 
    public static void main(String[] args) { 
    try { 
     Random r = new Random(); 
     Date test1start = new Date(); 
     for (int i = 0; i<= 50000; i++){ 
     Printable p = (Printable)Class.forName("P"+(r.nextInt(2)+1)).newInstance(); 
     System.out.println(p.getString()); 
     } 
     Date test1stop = new Date(); 
     Date test2start = new Date(); 
     for (int i = 0; i<= 50000; i++){ 
     Printable p; 
     if (r.nextInt(2) == 0) { 
      p = new P1(); 
     } else { 
      p = new P2(); 
     } 
     System.out.println(p.getString()); 
     } 
     Date test2stop = new Date(); 
     System.out.println("Test with 'Class' invocation took "+(test1stop.getTime()-test1start.getTime())+" milliseconds."); 
     System.out.println("Test with 'normal' invocation took "+(test2stop.getTime()-test2start.getTime())+" milliseconds."); 
    } catch (Exception e) { 
    } 
    } 
} 

interface Printable { 
    public String getString(); 
} 

class P1 implements Printable { 
    public String getString(){ 
    return "1"; 
    } 
} 

class P2 implements Printable { 
    public String getString(){ 
    return "2"; 
} 
    } 

答えて

6

あなたは間違いなくJavierのアドバイスに従ってください - 工場のレジストリはこの問題のための正しい方法です。私は過去に何度もそのように実装しました。フォーマット変換やその他の拡張可能な「述語」ベースのファクトリ・ソリューション(リフレクション情報に基づく自動GUI生成など)です。

しかし私はデザインに加えて、すべての翻訳者を対象とする共通ドメインモデル(CDM)の導入を提案します。 > B

  • A - - > C
  • B - > A

    • A:あなたはすべての順列を取得する - あなたはそれぞれの間の変換をサポートするために必要なフォーマットA、BおよびCがあるとし
    • B - > C
    • C - >
    • C - > B

    フォーマットの数が増えるにつれ、あなたは爆発を取得変換の!より良い考えは、各変換を2つの部分に分けることです。輸入者の輸出者と呼ぶことができます。輸入業者は、CDMから書式を共通ドメインモデル(CDM)に変換し、輸出はCDMから何らかの形式に変換します。

    は、一例として、我々は以下にAからBへの変換を分解:

    • A - > B(これはエクスポートである - > CDM
    • CDM(これは輸入です) )

    新しいフォーマットを追加したいときは、輸入者と輸出業者だけを書く必要がありますが、他のすべてのフォーマットとの間で翻訳があります。拡張性について話す!また、yoの読み込みが可能で、書き込みはできない形式も許可されます。

    したがって、解決策は、輸入業者の工場の登録簿と輸出業者の工場の登録簿を持つことです。

  • -1

    Class.forNameの1つの尺度で、コンパイル時の安全性を試してみてください。

    public class PrintableFactory 
    { 
        public enum Type 
        { 
         HTML, 
         DOC, 
        } 
    
        public static Printable getPrintable(final Type from, final Type to) 
        { 
         final Printable printable; 
    
         if(from == HTML && to == DOC) 
         { 
          printable = new HtmlToDoc(); 
         } 
         else if(from == DOC && to == HTML) 
         { 
          printable = new DocToHTML(); 
         } 
         else 
         { 
          // you decide if you want runtime or compile time exception handling 
          // could also return numm but I don't like that myself. 
          throw new ImpossibleConversionException(from, to); 
         } 
    
         return (printable); 
        } 
    } 
    
    +0

    ok ...これは好きではないのですか?あなたが投票した理由を言わないと、人々は投票から何かを学ぶことを期待していますか? – TofuBeer

    +0

    OPが明確に達成しようとしている拡張性がないためでしょうか? –

    3

    ファクトリメソッドを使用してください。 「大きいif」または名前の変更の代わりに、「クラス登録」メソッドを使用してください。このため、factoryクラスは、各具体クラスが条件(あなたの場合はソース名とターゲット名)とコンストラクタ(それは '条件 - >コンストラクタ'辞書)を登録するテーブルを保持します。ファクトリ自体は単純に辞書キーを構築し、必要なコンストラクタをフェッチします。

    大きな利点の1つは、各コンクリートクラスが解決する条件をカプセル化し、ファクトリメソッドを変更せずにさらに追加できることです。

    関連する問題