0

Beanを拡張するいくつかのオブジェクトがあります。

public class Fruit {}

public class Banana extends Fruit {}

public class Pear extends Fruit {}

そして、Beanごとに1つずつ、異なる実装のインターフェースがあります。

public interface Milkshake {
    public String doMilkshake();
}

public class FruitMilkshake implements Milkshake {
    public String doMilkshake() {
        return "Fruit Milkshake!";
    }
}

public class BananaMilkshake implements Milkshake {
    public String doMilkshake() {
        return "Banana Milkshake!";
    }
}

public class PearMilkshake implements Milkshake {
    public String doMilkshake() {
        return "Pear Milkshake!";
    }
}

Beanの具体的なタイプに基づいて、正しい実装をインスタンス化するにはどうすればよいですか?

今のところ、私は類型化とマップを使用して正しい実装を「マップ」しました。このような:

public void hungry(Fruit fruit) {
    Map<String, String> obj2impl = new HashMap<String, String>();
    obj2impl.put("Fruit", "FruitMilkshake");
    obj2impl.put("Banana", "BananaMilkshake");
    obj2impl.put("Pear", "PearMilkshake");

    String name = fruit.getClass().getCanonicalName();
    String implName = obj2impl.get(name);
    Milkshake milkshake = (Milkshake) Class.forName(implName).newInstance();

    milkshake.doMilkshake(fruit);
}



public interface Milkshake <T t> {
    public String doMilkshake(T t);
}

public class FruitMilkshake implements Milkshake<Fruit> {
    public String doMilkshake(Fruit fruit) {
        return "Fruit Milkshake!";
    }
}

public class BananaMilkshake implements Milkshake<Banana> {
    public String doMilkshake(Banana banana) {
        return "Banana Milkshake!";
    }
}

public class PearMilkshake implements Milkshake<Pear> {
    public String doMilkshake(Pear pear) {
        return "Pear Milkshake!";
    }
}

これを達成するためのより良い方法は?

4

2 に答える 2

1

これを達成するためのより良い方法は?

出発点は、クラスの名前を反映しないようにすることです。

Map<String, Class<? extends Milkshake>> obj2impl =
    new HashMap<String, Class<? extends Milkshake>>();
obj2impl.put("Fruit", FruitMilkshake.class);
obj2impl.put("Banana", BananaMilkshake.class);

...

Milkshake milkshake = obj2impl.get(text).newInstance();

これでも、各実装にパラメーターなしのコンストラクターが必要であり、常に新しいインスタンスが作成されます。Providerのような概念を使用する場合は、これを回避できます。

Map<String, Provider<Milkshake>> map = ...;
// Fill the map with providers, some of which could create a new instance,
// and some could reuse an existing one

...

Milkshake milkshake = map.get(text).get();

編集:投稿を読み直したら、テキスト部分も削除して、を作成できますMap<Class<?>, Provider<Milkshake>>。可能であれば、クラスの名前をハードコーディングしないでください。

もちろん、FruitクラスにmakeMilkshake抽象メソッドがある場合、それはさらに良いでしょう...

于 2012-08-24T07:25:33.237 に答える
0
public class Fruit {
    public Class<? extends Milkshake> getMilkshakeClass() {
        return Milkshake.class;
    }
}

public class Banana extends Fruit {
    public Class<? extends Milkshake> getMilkshakeClass() {
        return Banana.class;
    }
}

public class Pear extends Fruit {
    public Class<? extends Milkshake> getMilkshakeClass() {
        return PearMilkshake.class;
    }
}

上記で使用したメソッドをオーバーライドする必要のある抽象メソッドとして持つAbstractFruitクラスを作成することもできます。

public abstract class AbstractFruit {
    public abstract Class<? extends Milkshake> getMilkshakeClass();
}

そして、彼らにフルーツを拡張させるのではなく、それを拡張します。

于 2012-08-24T07:29:39.227 に答える