考虑一个多人格斗游戏,客户端通过向服务器发送一个包含刚选择的战斗机名称的字符串来选择战斗机。
考虑服务器中的“战士”类结构:
Fighter
Foo extends Fighter
Bar extends Fighter
Qux extends Fighter
例如客户端发送了这个
"Bar"
字符串,如何根据该字符串初始化子类?我这样做的方式是像这样的
enum
:public enum Champion {
Foo {
@Override
public Fighter getNew() {
return new Foo();
}
},
Bar {
@Override
public Fighter getNew() {
return new Bar();
}
},
Qux {
@Override
public Fighter getNew() {
return new Qux();
}
};
public abstract Fighter getNew();
public static boolean contains(String fighter) {
for (Champion c : Champion.values()) {
if (c.name().equals(fighter)) {
return true;
}
}
return false;
}
}
然后我得到一个像这样的对象:
public Fighter getFighter(String fighterName) {
if(Champion.contains(fighterName)) {
return Champion.valueOf(fighterName).getNew();
} else {
return null;
} // For example sake only :)
}
这是处理这种遭遇的正确方法吗?有没有更好的办法?我记得有一种已知的方式可以处理此类相遇,但无法确切记住哪种方式。
如果您有想法,请告诉我!
最佳答案
使用工厂,解决方案如下所示:
interface FighterFactory {
Fighter create();
}
在外观中保留一个
Map<String, FighterFactory>
变量。每个Fighter
类型都必须在其工厂图中注册。private Map<String, FighterFactory> fighters;
public void register(String name, FighterFactory factory) {
fighters.put(name, factory);
}
在每种
Fighter
类型中嵌入一个内部类Factory
,例如class Foo extends Fighter {
//code for Foo
public static class Factory implements FighterFactory {
public Foo create() {
return new Foo();
}
}
}
// and in your Facade
register("Foo", new Foo.Factory());
要实例化新的Fighter,请进入Fighter-Map并对其结果执行create。
FighterFactory factory = fighters.get(nameFromClient);
// null handling, if nameFromClient is not a Fighter type;
return factory.create();
与反射相比,此设计具有一些优点:
以及单一工厂方法(一种方法可处理所有Fighter类型):
和枚举方法: