默认情况下,enum 类型只有一组值。 enum 类型中的值实际上声明为 static final,并且无法在运行时添加更多。
话虽如此,您还可以使用其他模式来实现您想要的。让我们看一下使用接口和注册系统。我们将从Terrain 接口开始:
public interface Terrain {
int getId();
String getName();
int getSightBonus();
}
现在是enum、DefaultTerrain:
public enum DefaultTerrain implements Terrain {
PLAINS(0, "Plains", 1),
HILLS(1, "Hills", -1),
MOUNTAINS(2, "Mountains", -2);
private int id;
private String name;
private int sightBonus;
private DefaultTerrain(int id, String name, int sightBonus) {
this.id = id;
this.name = name;
this.sightBonus = sightBonus;
}
public int getId() {return id;}
public String getName() {return name;}
public int getSightBonus() {return sightBonus;}
}
还有一个注册类,可以是静态实用程序类,也可以是单例类。
public class TerrainManager {
private static Map<Integer, Terrain> terrainsById = new HashMap<>();
static {
for (DefaultTerrain terrain : DefaultTerrain.values())
register(terrain);
}
public static void register(Terrain terrain) {
Integer id = terrain.getId();
if (terrainsById.contains(terrain.getId()))
throw new IllegalArgumentException("Terrain with id already exists: " + id);
terrainsById.put(id, terrain);
}
public static Terrain getTerrainById(int id) {
return terrainsById.get(id);
}
public static Set<Terrain> getAllTerrains() {
return new HashSet<Terrain>(terrainsById.values());
}
}
最后一节课是魔法发生的地方。大概模组制作者会在游戏的世界定义中使用某种标识符来表示“使用此图块”,对吧?在这种情况下,我称它为整数id,但实际上它可以是任何类型,只需相应地修改Map。在地图加载代码中,只需使用世界定义中的 ID 查找Terrain。当修改者添加新的Terrain 时,他们只需要实现Terrain 并将其注册到TerrainManager。
static 初始化程序确保在添加任何其他内容之前添加您的 DefaultTerrain 对象。如果您使用单例,则可以将其放入类构造函数中。
将此模式用于您希望用户添加的不同 enum 类型。除了enum,您还可以将它用于几乎任何其他类型。