Java 从ResultSet创建复杂对象

Java 从ResultSet创建复杂对象,java,sqlite,jdbc,Java,Sqlite,Jdbc,SQLite和Java初学者在这里 我目前正在开发一个游戏,玩家可以获得随机物品,因为我计划包含大量物品,所以我将物品信息存储在SQLite数据库中 问题是,除了字符串名称、整数幂等字段外,我的项对象还有自己的行为对象。这使得将结果转换为对象变得更加复杂。目前,我将这些行为称为数据库中的字符串,然后在创建项时使用Switch语句实例化正确的行为对象。这只是一个半虚构的例子来说明我的意思: Item item = new Item(); String name = resultSet.getSt

SQLite和Java初学者在这里

我目前正在开发一个游戏,玩家可以获得随机物品,因为我计划包含大量物品,所以我将物品信息存储在SQLite数据库中

问题是,除了字符串名称、整数幂等字段外,我的项对象还有自己的行为对象。这使得将结果转换为对象变得更加复杂。目前,我将这些行为称为数据库中的字符串,然后在创建项时使用Switch语句实例化正确的行为对象。这只是一个半虚构的例子来说明我的意思:

Item item = new Item();

String name = resultSet.getString("Name");
String activationEffect = resultSet.getString("Activation Effect");

item.setName(name);

switch (activationEffect){
    case "Smack Fools":
        item.setActivationEffect(new SmackFools());
        break;
    case "Have a Nap":
        item.setActivationEffect(new NapTime());
        break;
    default:
        break;

或者,我可以让item.setActivationEffect接受一个字符串并执行switch语句本身,但这并不能真正改变任何事情。有没有更好的方法来实现这一点?

您需要一种方法来将每个行为名称(一个
字符串
)与其类关联起来(以创建该类的新对象)。由于行为名称与类名称不完全相同,因此不能直接使用反射来实现此目的。
所以没办法,你必须做一张桌子。
有很多方法可以做到这一点,你的开关是一个有效的一个。虽然你可能不喜欢它的冗长;每个新行为需要三行代码

在下面的代码中,所有这些都被隔离在一个类中。
每次添加新行为时,只需添加一行。
我假设所有行为都扩展了一个公共
ActivationEffect
类,或者所有行为都实现了一个公共
ActivationEffect
接口

class ActivationEffectsFactory {
    private static Map<String, Class<? extends ActivationEffect>> map = new HashMap<>();
    static
    {
        add( "Smack Fools", SmackFools.class );
        add( "Have a Nap", Naptime.class );
    }

    private static void add(String name, Class<? extends ActivationEffect> behaviour) {
        assert !map.containsKey(name);
        assert behaviour!=null && name!=null;
        map.put(name, behaviour);
    }

    public static ActivationEffect build(String name) 
    {
        ActivationEffect res;
        try {
            res = map.get(name).newInstance();
        } catch (InstantiationException | IllegalAccessException ex) {
            res = null;
        }
        if ( res==null )
            throw new IllegalArgumentException( "Incorrect behaviour name : " + name );
        return res;
    }
}
factory模式将对您有用:

假设您的类
smackfool
NapTime
有一个名为
ActivationEffect
的公共超类,您必须这样编码一个工厂类:

class EffectFactory
{
    private final Map<String, Class> map=createMap();

    private Map<String, Class> createMap()
    {
        Map<String, Class>  map=new HashMap<String, Class> ();
        // ... Store here the allowed mappings:
        // map.put("Smack fools", my.package.SmackFools.class);
        // map.put("Have a nap", my.package.NapTime.class);
        return map;
    }

    public ActivationEffect createActivationEffect(String name){
        // ... Get a Class indexing the map by name, and instantiate it.
        // If not found, throw an exception (for example, IllegalArgumentException).
    }
}

每个问题只能问一个问题。更重要的是,考虑到你的两个问题完全不同。请移开你的第二个。你可以再问一个问题。它将帮助您获得更多更好的答案。在关系数据库中存储对象图的一种非常简单的方法是让您的类实现
Serializable
,然后将整个序列化对象图存储在数据库列中。您可以通过将对象“字符串化”为JSON
String
字符串,然后将该字符串保存到数据库字段来执行类似的操作。序列化的表单和JSON
字符串都可以反序列化到原始对象中。必须小心谨慎,以使序列化表单高效且正确。
class EffectFactory
{
    private final Map<String, Class> map=createMap();

    private Map<String, Class> createMap()
    {
        Map<String, Class>  map=new HashMap<String, Class> ();
        // ... Store here the allowed mappings:
        // map.put("Smack fools", my.package.SmackFools.class);
        // map.put("Have a nap", my.package.NapTime.class);
        return map;
    }

    public ActivationEffect createActivationEffect(String name){
        // ... Get a Class indexing the map by name, and instantiate it.
        // If not found, throw an exception (for example, IllegalArgumentException).
    }
}
final class EffectFactory
{
    private static final EffectFactory INSTANCE=new EffectFactory();

    public static EffectFactory getInstance()
    {
        return INSTANCE;
    }

    private EffectFactory(){}

    // ...
}