2013-08-25 6 views
12

反射を工場パターンで使用することをお勧めしますか?工場パターンで反射を使用する

public class MyObjectFactory{ 
private Party party; 

public Party getObject(String fullyqualifiedPath) 
{ 
    Class c = Class.forName(fullyqualifiedPath); 
    party = (PersonalParty)c.newInstance(); 
    return party; 
} 
} 

PersonalPartyはそれをこの方法(Class.forNameのを)リフレクションを使用して党

+1

これに重大な用途がありますか?一般に、私は最後の手段として反射を考慮する。特にこの目的のために。 –

+0

アノテーションを使用するJSf2.0のようなフレームワークはどうですか?実行時にオブジェクトをインスタンス化するためにReflection APIを使用する必要がありますか? – Ullas

+1

JSFについては、そのままタグを付けてください。 –

答えて

9

ファクトリパターンの目的は、DE-夫婦するいくつかのコードを、それが消費するオブジェクトの実行時の型からのもので使用することができます

// This code doesn't need to know that the factory is returning 
// an object of type `com.example.parties.SurpriseParty` 
AbstractParty myParty = new PartyFactory().create(...); 

このようなコードを使用して、 PartyFactoryは、どのランタイムタイプを使用すべきかを正確に判断または知る責任があります。

あなたは、必要なクラスの完全修飾名を渡すことで、この利点を享受できます。どのようにこの...

// This code obviously DOES know that the factory is returning 
// an object of type `com.example.parties.SurpriseParty`. 
// Now only the compiler doesn't know or enforce that relationship. 
AbstractParty myParty = new PartyFactory().create("com.example.parties.SurpriseParty"); 

...単にタイプcom.example.parties.SurprisePartyのものとしてmyPartyを宣言すると何が違いますの?最後に、あなたのコードは同じように結合されますが、静的型の検証をやめました。これは、Javaの強力な型付けの利点のいくつかを放棄している間に、利益が得られないことを意味します。 com.example.parties.SurprisePartyを削除してもコードはコンパイルされますが、IDEはエラーメッセージを表示せず、実行時までこのコードとcom.example.parties.SurprisePartyの間に関係があったことを認識しません。次

// I took the liberty of renaming this class and it's only method 
public class MyPartyFactory{ 

    public Party create(String name) 
    { 
     //TODO: sanitize `name` - check it contains no `.` characters 
     Class c = Class.forName("com.example.parties."+name); 
     // I'm going to take for granted that I don't have to explain how or why `party` shouldn't be an instance variable. 
     Party party = (PersonalParty)c.newInstance(); 
     return party; 
    } 
} 

:メソッドの引数は、完全修飾名単純なクラス名ではありませんので

非常に少なくとも

、私は、少なくとも、このコードを変更することをアドバイスしたい、それがに悪い習慣ですClass.forName(...)を使用しますか?それは代替案が何であるか、そしてそれらのString引数(name)とこのファクトリが提供するクラスとの関係に依存します。代替案が大きな条件である場合:

if("SurpriseParty".equals(name) { 
    return new com.example.parties.SurpriseParty(); 
} 
else if("GoodbyeParty".equals(name)) { 
    return new com.example.parties.GoodbyeParty(); 
} 
else if("PartyOfFive".equals(name)) { 
    return new com.example.parties.PartyOfFive(); 
} 
else if(/* ... */) { 
    // ... 
} 
// etc, etc etc 

...これはスケーラブルではありません。このファクトリが作成する実行時の型の名前とname引数の値の間にはっきりとした関係があるので、代わりにClass.forNameの使用を検討する必要があります。そうすれば、新しいPartyタイプをシステムに追加するたびに、Factoryオブジェクトがコード変更を必要としないように保護されます。


代わりにAbstractFactoryパターンを使用することも考えられます。あなたのかかるコードは次のようになります場合:要求され、多くの場合に発生するパーティの種類の数が限られている

AbstractParty sParty = new PartyFactory().create("SurpriseParty"); 
AbstractParty gbParty = new PartyFactory().create("GoodByeParty"); 

...、あなたが当事者のこれらの種類ごとに異なる方法を検討する必要があり:

...Javaの静的型付けを活用することができます。

このソリューションは、新しいタイプのPartyを追加するたびにファクトリオブジェクトを変更する必要があることを意味します。反射ソリューションかAbstractFactoryのどちらがより良い解決策であるかは、タイプPartyを追加します。新しいタイプの毎日?反射を使用します。 10年ごとに新しいパーティタイプですか? AbstractFactoryを使用してください。

+0

詳細な説明をいただきありがとうございます。 – Ullas

+0

@Ullas - 私の喜びです。 'AsbtractFactory'を使うべきときに、反射的な解決策を使うべきときに強調したもう一つの段落を加えました。 –

1

はほとんど常に悪いアプリケーション設計のサインです実装しています。いくつかの種類があります。例えば、外部ライブラリやプラグインのような動的な負荷をかけている場合など、その使用はOKです。

1

APIと、ユーザーがプラグインのクラス名を追加できるXML設定ファイルを提供するAPIに使用できます。その後、はい、あなたはこれが

関連する問題