枚举和工厂策略的组合可用于一种简单的、类型安全的从字符串创建对象实例的方法,并用于提供一组字符串(或数组)。
举个例子——
import java.util.HashMap;
import java.util.Map;
public enum FishType {
BLUE_FISH(BlueFish.class, new FactoryStrategy<BlueFish>(){
public BlueFish createFish(int x, int y) {
return new BlueFish(x, y);
}}),
RED_FISH(RedFish.class, new FactoryStrategy<RedFish>(){
public RedFish createFish(int x, int y) {
//an example of the increased flexibility of the factory pattern - different types can have different constructors, etc.
RedFish fish = new RedFish();
fish.setX(x);
fish.setY(y);
fish.init();
return fish;
}});
private static final Map<Class<? extends Fish>, FactoryStrategy> FACTORY_STRATEGY_MAP = new HashMap<Class<? extends Fish>, FactoryStrategy>();
private static final String[] NAMES;
private FactoryStrategy factoryStrategy;
private Class<? extends Fish> fishClass;
static {
FishType[] types = FishType.values();
int numberOfTypes = types.length;
NAMES = new String[numberOfTypes];
for (int i = 0; i < numberOfTypes; i++) {
FishType type = types[i];
FACTORY_STRATEGY_MAP.put(type.fishClass, type.factoryStrategy);
NAMES[i] = type.name();
}
}
<F extends Fish> FishType(Class<F> fishClass, FactoryStrategy<F> factoryStrategy) {
this.fishClass = fishClass;
this.factoryStrategy = factoryStrategy;
}
public Fish create(int x, int y) {
return factoryStrategy.createFish(x, y);
}
public Class<? extends Fish> getFishClass() {
return fishClass;
}
public interface FactoryStrategy<F extends Fish> {
F createFish(int x, int y);
}
@SuppressWarnings("unchecked")
public static <F extends Fish> FactoryStrategy<F> getFactory(Class<F> fishClass) {
return FACTORY_STRATEGY_MAP.get(fishClass);
}
public static String[] names() {
return NAMES;
}
}
然后可以通过以下方式使用此枚举 -
Fish fish = FishType.valueOf("BLUE_FISH").create(0, 0);
或者
Fish fish = FishType.RED_FISH.create(0, 0);
或者,如果您需要知道创建的鱼的类型,您可以使用此调用 -
BlueFish fish = FishType.getFactory(BlueFish.class).createFish(0, 0);
要填充菜单中的项目或出于任何其他原因获取所有鱼类类型,您可以使用 names() 方法 -
String[] names = FishType.names();
要添加新类型,唯一需要编辑的代码是添加一个新的枚举声明,例如
GREEN_FISH(GreenFish.class, new FactoryStrategy<GreenFish>(){
public GreenFish createFish(int x, int y) {
return new GreenFish(x, y);
}}),
它可能看起来有很多代码,但它已经编写好了,它提供了一个干净的 API 来从其他代码调用,它提供了很好的类型安全性,允许 fish 实现灵活地拥有他们想要的任何构造函数或构建器,它应该是快速执行的,并且它不需要您传递任意字符串值。
如果您真的想保持简洁,您还可以在枚举中使用模板方法 -
公共枚举 FishType {
BLUE_FISH(){
public BlueFish create(int x, int y) {
return new BlueFish(x, y);
}
},
RED_FISH(){
public RedFish create(int x, int y) {
return new RedFish();
}
};
public abstract <F extends Fish> F create(int x, int y);
}
有了这个,您仍然可以获得许多相同的功能,例如
Fish fish = FishType.valueOf("BLUE_FISH").create(0, 0);
和
Fish fish = FishType.RED_FISH.create(0, 0);
乃至
RedFish fish = FishType.RED_FISH.create(0, 0);