Java 从枚举引用创建对象

Java 从枚举引用创建对象,java,enums,Java,Enums,如果我有一个标准枚举(在本例中是一个建筑物列表的表示),例如: public enum BuildingType { farm, shop, house } 以及基于“building”超类创建对象的函数,例如: public void addBuilding(BuildingType bType) { Building b = new Building(); b.start(); } 我的所有子类的名称都与BuildingType枚举匹配。 有没有一种方法可以在没有cla

如果我有一个标准枚举(在本例中是一个建筑物列表的表示),例如:

public enum BuildingType {
   farm, shop, house
}
以及基于“building”超类创建对象的函数,例如:

public void addBuilding(BuildingType bType) {
   Building b = new Building();
   b.start();
}
我的所有子类的名称都与BuildingType枚举匹配。 有没有一种方法可以在没有class语句的情况下使用enum参数设置对象b的类

显然是错误的,但类似这样的

Building b = new bType(); //using the argument

一如既往地感谢您。

如果建筑物的不同行为在类层次结构中表示,而不是在枚举文本中表示,这将是一种更适合面向对象的方式,即拥有一个农场建筑物,实现建筑特定行为的建筑抽象基类的ShopBuilding和HouseBuilding子类。

您可以创建一个参数,声明每个枚举引用的类类型。它可能是这样的:

// Enums should be all caps btw
public enum BuildingType {
   FARM(Farm.class), SHOP(Shop.class), HOUSE(House.class);
   private Class<? extends Building> type;
   private BuildingType(Class<? extends Building> type) {
       this.type = type;
   }

   public Class<? extends Building> getType() {
       return type;
   }
}

本示例假定您的类也有一个默认的无参数构造函数,所以请注意这一点。

我建议您阅读有关设计模式的内容,尤其是有关Factory模式的内容。这里有一个wiki链接,但是你可以在互联网上找到大量的例子。 比如说

BuildingFactory bf = BuildingFactory.newInstance();
Building b = bf.createBuilding(bType);
在createBuilding方法中:

// return Building superclass which you can cast to specific type

public Building createBuilding(BuildingType bType) {
 if(bType == something) {
    return new FarmBuilding();
 }
 else if(...) {
    return something else;
 }
}

您可以定义一个枚举,该枚举也是:

无论哪种方式,都可以使用:

public void addBuilding(BuildingType bType) {
   Building b = bType.createBuilding();
   b.start();
}

像上面状态的一些答案一样,您可以使用抽象方法在枚举上实现它们。与许多人所说的不同,您可以使用反射来实例化带有参数的对象,如下所示:

public enum BuildingType{
农场(农场类)、商店(商店类)、房屋(房屋类);

私有最终类如何将其与抽象工厂设计模式相统一,即让枚举创建建筑?@Katona我认为枚举中的这种类型的类对于任何工厂样式的设计模式都不理想。在枚举中修复可创建的类型是关闭其他人可能希望置于顶部的任何进一步层次结构的开关。如果你在一个设定的环境中就像一个游戏,不管怎样,但是如果你建立一个某种框架,我认为这不是一个好主意。特别是因为它真的没有必要。有什么理由使用反射吗?枚举可以简单地用构造函数实例化建筑,对吗?@katona你不能在构造函数中这样做,因为那样的话您每次都会返回同一个建筑实例,但您可以使用枚举上的抽象工厂模式,并让枚举本身成为工厂。请参阅更新的答案。答案很好。是否有理由避免反射?我对此没有任何经验。@TrewTzu反射通常“不太安全”,因为编译器无法检查大多数操作。在本例中,对
newInstance()
的调用假定存在默认构造函数。如果没有,则在运行时抛出异常(将来可能会出现这种情况),而在非反射版本中,则在编译时检测问题(更容易检测和修复)此外,还可以为每种类型定制结构,例如归还新房(3)
eg适用于3间卧室或任何地方,甚至基于区域设置,甚至委托给注入工厂。很高兴看到更新,这正是我在上一篇评论中的意思。使用构造函数使其可读性降低…无论如何,这是一个很好的答案!没有设计模式工厂。有工厂方法、抽象工厂,而不仅仅是工厂。。.
public enum BuildingType {
    farm(Farm.class),
    shop(Shop.class),
    house(House.class);
    private Class<? extends Building> clazz;
    private BuildingType(Class<? extends Building> clazz) {
        this.clazz = clazz;
    }

    public Building createBuilding() {
        try {
            return clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new RuntimeException(clazz + " has no default constructor");
        }
    }
}
public enum BuildingType {
    farm() {
        public Building createBuilding() {
            return new Farm();
        }
    },
    shop() {
        public Building createBuilding() {
            return new Shop();
        }
    },
    house() {
        public Building createBuilding() {
            return new House();
        }
    };

    public abstract Building createBuilding();
}
public void addBuilding(BuildingType bType) {
   Building b = bType.createBuilding();
   b.start();
}