0

私はFoo.java、インターフェースであるを持っています。

そしてそれを実装する多くのクラス。Bar1.java , Bar2.java

フロントエンドに次のようなメソッドがあります。getBar(String bar)

私はこのようにそれを行うことができます:

if(bar.equals("Bar1")) {
    return new Bar1();
}

しかし、どういうわけかそれを行うことができますか?新しい何かが実装されるたびに、新しいステートメントFoo.javaでメソッドを更新する必要はありません。ELSE

それぞれの実装には、作成するたびに一意のIDなどが追加さBarX.javaれると思いました。

何か提案や考えはありますか?多分私は使用するenumか、smthingまたは他の解決策を使用できると思いました。

4

6 に答える 6

2

参考までに: もちろん、これを書くべきではないことはわかっています。

if(bar == "Bar1") {
    return new Bar1();
}

このようにする必要があります:

if("Bar1".equals(bar)) {
    return new Bar1();
}

ファクトリ(別名仮想コンストラクタ)が必要なようです。すべての Foo 実装者がデフォルトのコンストラクターを持っている場合、これを行うことができます:

public class FooFactory {

    public static Foo create(Class<Foo> clazz) {
        return clazz.newInstance();
    }

    public static Foo create(String className) {
        return create(Class.forName(className));
    }
}

処理すべき例外があります。それらを綴る時間はありません。あなたはその考えを見るべきです。新しいクラスを作成するだけで、ファクトリでそれを処理できます。

他のコンストラクターがある場合は、パラメーターと追加の呼び出しを使用してテーマを詳しく説明してください。これで始められるはずです。

于 2012-10-04T13:34:07.860 に答える
2

依存性注入またはリフレクションの仕事のように思えます。

できるよ :

Class myClass = Class.forName("my.namespace.MyClass");

それは反省を伴うでしょう。あまりいいことではありませんが、仕事をしています。

于 2012-10-04T13:35:28.033 に答える
1

クラス名でオブジェクトを作成できます:

Class<?> clazz = Class.forName(className);
Object object = ctor.newInstance();

または、特定のコンストラクターを呼び出す必要がある場合 (たとえば、1 つのString引数strArgumentを使用):

Constructor<?> c = clazz.getConstructor(String.class);
Object object = c.newInstance(new Object[] { strArgument });
于 2012-10-04T13:38:08.523 に答える
0

- Reflection行く方法です...

-しかし、それでもあなたはこのような方法を使うことができます

public static Foo createObj(Class<Foo> clazz) {
    return clazz.newInstance();
}

-そして言うまでもなく、そうあるべきでequals()あり、そうではないということです ==

if(bar.equals("Bar1")) {
    return new Bar1();
}
于 2012-10-04T13:43:18.090 に答える
0

リフレクションを使用すると、パッケージ全体をスキャンしてすべてのBarXクラスを検索し、入力がリストに存在するかどうかをインスタンス化してこのリストを操作できます。または、エラーを直接キャッチするClass.forNameソリューションを使用することもできます。編集:これをチェックしてくださいhttp://code.google.com/p/reflections/

于 2012-10-04T13:49:26.067 に答える
0

これは、古典的な工場パターンの問題です。

解決策は、静的マップを維持する必要があるときはいつでも、新しい「バー」タイプがあるときはいつでも、最初にそれをマップに登録する必要があるため、そのタイプのオブジェクトが必要なときはいつでも、マップから選択するだけです。

以下のクラスを検討してください

interface IVehicle {
    public void drive();
    public void stop();
}

class Car implements IVehicle {

    public void drive(){
        //logic goes here
    }

    public void stop(){
        //logic goes here
    }
}

class VehicleFactory{

    public IVehicle createVehicle(String VehicleType){
        IVehicle vehicle = null;

        if("Car".equalsIgnoreCase(VehicleType) ){
            vehicle = new Car();
        }
        if("Bus".equalsIgnoreCase(VehicleType) ){
            //vehicle = new Bus();
        }
        if("Train".equalsIgnoreCase(VehicleType) ){
            //vehicle = new Train();
        }
        return vehicle;
    }
}

したがって、新しいタイプの車両があるときはいつでも、新しいタイプの車両のコードを追加して方法を変更する必要があります。

解決策は、VehicleFactory クラスを以下のように改善することです。すべての車両タイプは、以下に示すようにマップに登録する必要があります。

class Car implements IVehicle {

    static{
        VehicleFactoryFlexible.registerVehicle("Car", new Car());
    }
    public void drive(){
        //logic goes here
    }

    public void stop(){
        //logic goes here
    }

    public IVehicle createVehicle(){
        return (IVehicle) new Car();
    }
}

public class VehicleFactoryFlexible {

    static Map vehicleRegistry = new HashMap();

    public static void registerVehicle(String vehicleType, IVehicle veh){
        vehicleRegistry.put(vehicleType, veh);
    }

    public IVehicle createVehicle(String vehicleType){
        IVehicle vehicle = (IVehicle)vehicleRegistry.get(vehicleType);
        return vehicle.createVehicle();
    }
}
于 2012-10-04T13:40:18.903 に答える