2015-08-16 42 views
0

SQLite和这里Java初学者,创建从ResultSet中复杂对象

我目前工作的一个游戏,玩家随机获得物品,因为我计划包括一个巨大的项目的数量,我已存储的项目信息在SQLite数据库。

事情是,我的项目对象除了像字符串名称,诠释权力等字段有自己的行为对象。这使得转换结果为对象更复杂的努力。目前,我将这些行为称为db中的Strings,然后在Item Creation中使用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采用String,做switch语句本身,但并没有真正改变任何东西。有没有更好的方法来完成这一点?

+1

你应该只问每个问题一个问题。考虑到你的两个问题是完全不同的。请删除你的第二个。你可以就此提出另一个问题。它会帮助你得到更多更好的答案。 –

+0

好的,会做的。 – dGFisher

+0

将对象图存储在关系数据库中的一种非常简单的方法是让您的类实现“Serializable”,然后将整个序列化对象图存储在数据库列中。您可以通过将对象“串化”为JSON String来做类似的事情,然后将字符串保存到数据库字段中。序列化表单和JSON'String'都可以反序列化为原始对象。必须小心谨慎,以确保序列化表格的高效性和正确性。 – scottb

回答

1

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

在下面的代码中,所有这些都被隔离在一个类中。
每次添加新行为时,只需添加一行。
我假设所有行为扩展了一个普通的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; 
    } 
} 

当你想添加一个新的效果,你只需要在静态块中这样做。
从它的名字,你会得到正确的类的新对象:

item.setActivationEffect(ActivationEffectsFactory.build(activationEffect)); 
1

工厂格局将是对您有用:

假设你的类SmackFoolsNapTime有一个共同的超命名,例如,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). 
    } 
} 

在这样,如果您想添加ActivationEffect的新实现,则只需在createMap中添加一行即可。如果您希望它更加灵活,可以将映射存储在.properties文件中,并修改createMap以读取该文件。

在这种情况下,另一个附加有用的模式将实现工厂作为

final class EffectFactory 
{ 
    private static final EffectFactory INSTANCE=new EffectFactory(); 

    public static EffectFactory getInstance() 
    { 
     return INSTANCE; 
    } 

    private EffectFactory(){} 

    // ... 
}