代码之家  ›  专栏  ›  技术社区  ›  Johann MARTINET

从磁盘解析/加载对象

  •  0
  • Johann MARTINET  · 技术社区  · 6 年前

    我正在开发一个从文件中读取不同格式数据的程序。为了解释我的需求,为了清楚起见,这里有一个例子(实际上是最小/简单的例子,数据格式在现实中相当复杂)

    public class Person{
        private final String name;
    
        public Person(String name){
            this.name = Objects.requireNonNull(name);
        }
    
        public String getName(){return name;}
    }
    

    然后我需要创建 Person 使用具有以下格式的文件初始化:

    name = Bob
    

    (NB):在这个例子中,我使用Java属性格式,但事实上,格式是不同的,并且有大量的数据。例如,我要加载的一个类有50多个字段(包括double/string/arrays)。从~30m的文件加载,格式固定)

    为了加载这些文件,我考虑了三种方法:

    第一: 提供静态工厂方法:

    public class Person{
        /*Fields, Constructors, Getters, ... */
        //...
        public static Person fromFile(Path path){/*implementation*/}
    }
    

    但是person类应该只是一个“data”类,使用这种方法,我必须在一个看起来很奇怪的“data”类中处理ioexception。 此外,加载对象的实例(在现实中)可能相当复杂,并且意味着许多与Read类无关的方法/ReGeX/Java文件实用工具。

    第二: 提供实用程序类:

    public final class PersonLoader{
        /**Prevents instantiation*/
        private PersonLoader(){}
    
        public static Person load(Path path){/*implementation*/}
    }
    

    这种方法的主要问题是,一旦释放这两个类,我就应该维护它们。我没有办法强迫(用编译器)有一个专用的实用程序类。两个月后,如果我添加另一个格式,我会考虑添加一个实用程序类吗?(我猜:没有)

    第三: 使用加载程序实例加载

    这可以是这样的外部或内部类(也可以是单例类):

     public (static) class PersonLoader{
         public PersonLoader(){}
    
         public Person load(){/*implementation*/}
     }
    

    如果我将此方法用作内部类(静态版本),则此方法似乎结合了以前方法的两个缺点。 如果我将其用作顶级类,维护问题仍然存在,并且每次要加载数据时都需要创建另一个对象实例。 即使我使用singleton模式,拥有20个singleton(对于我使用的每种格式)似乎也是个坏主意。

    有没有其他方法可以做到这一点,或者我应该重构其中一种方法来满足我的需要?

    1 回复  |  直到 6 年前
        1
  •  0
  •   MyYyY    6 年前

    我认为你可以有一个通用的加载器(你也可以使它成为单一的)

    public class ObjectLoader<OBJECT_TYPE> {
    
        public  OBJECT_TYPE create(Class<OBJECT_TYPE> type, String path){
            OBJECT_TYPE newObj = null;
            try{
                newObj = type.newInstance();
                Field[] declaredFields = type.getDeclaredFields();
                for (Field declaredField : declaredFields) {
                    declaredField.setAccessible(true);
                    declaredField.set(newObj, "PUT HERE NECESSARY VALUE ");
    
            }
            }catch (InstantiationException e) {
                //TODO: Handle error
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                //TODO: Handle error
                e.printStackTrace();
            }
            return newObj;
        }
    }
    

    使用Java反射来实例化对象