我有一个自定义的INIFile类,我编写了读/写包含标题下字段的INI文件。我有几个类,我想使用这个类序列化,但我有点困惑,最好的方法去做。我考虑了两种可能的方法。
方法1:定义像ObjectPersistent这样的接口,强制执行两个方法,如下所示:
public interface ObjectPersistent
{
public void save(INIFile ini);
public void load(INIFile ini);
}
然后,每个类都负责使用INIFile类将所有属性输出到文件中。
方法2:通过getter / setter公开需要序列化的类的所有属性,以便可以在一个集中的位置处理保存,如下所示:
public void savePlayer(Player p)
{
INIFile i = new INIFile(p.getName() + ".ini");
i.put("general", "name", p.getName());
i.put("stats", "str", p.getSTR());
// and so on
}
方法1的最佳部分是并非所有属性都需要暴露,因此封装保持牢固。方法1的不好之处在于,技术上保存并不是玩家会“做”的事情。它还通过传递给方法的ini对象将我绑定到平面文件,因此稍后切换到关系数据库将是一个巨大的痛苦。
方法2的最佳部分是所有I / O都集中在一个位置,实际的保存过程对您完全隐藏。它可以保存到平面文件或数据库。方法2的不好之处在于我必须完全公开类内部成员,以便集中式序列化程序可以从类中获取所有数据。
我希望尽可能简单。我更喜欢在不使用框架的情况下手动执行此操作。我也对使用Java提供的内置序列化不感兴趣。这里有什么我想念的吗?关于什么样的模式最适合这个的任何建议,我将不胜感激。感谢。
答案 0 :(得分:4)
由于您不希望(出于某种原因)使用Java序列化,因此可以使用XML序列化。最简单的方法是通过XStream:
XStream是一个简单的库,用于将对象序列化为XML,然后再返回。
如果您确定不想使用任何序列化框架,那么您当然可以使用反射。重要的一点是:
getClass().getDeclaredFields()
返回班级的所有字段 - 公共和私人field.setAccessible(true)
- 通过反射访问私人(或受保护)字段Modifier.isTransient(field.getModifiers())
会告诉您该字段是否已使用transient
关键字标记 - 即不符合序列化条件。team.coach.name
。所有序列化库都使用反射(或introspection)来实现其目标。
答案 1 :(得分:1)
我会选择方法1。
它可能不是最面向对象的方式,但根据我的经验,它比方法2更简单,更不容易出错并且更易于维护。 如果您对为自己的序列化提供多个实现感到惋惜,可以使用接口来保存和加载方法。
public interface ObjectSerializer
{
public void writeInt(String key, int value);
...
}
public interface ObjectPersistent
{
public void save(ObjectSerializer serializer);
public void load(ObjectDeserializer deserializer);
}
您可以改进这些ObjectSerializer / Deserializer接口,以获得足够的方法和参数来涵盖平面文件和数据库案例。
答案 2 :(得分:0)
这是访客模式的工作。