我有一个类Data,它以String的形式存储单个数据,它还存储应该转换此数据的类型,该类型存储为枚举常量(仅允许用于specyfic类型)。描述一个项的数据对象存储在DataItem类中。意图是Data对象对应于表中的字段,DataItem表示完整行。同样重要的是要提到Data对象是从DataTemplate类创建的,它指定在何处查找此类数据及其类型(因此每个Data的类型应在编译时知道)。
我希望这个程序在数据库选择方面非常灵活,所以方法" save"来自存储接口,允许在实现后使用任何类型的存储(文件/ RDB /文档数据库......)。
我想知道将这些String值从Data对象转换为适当类型的好方法,这样我就可以将它们保存到数据库中。一种简单的方法是使用这样的东西:
public void save(DataItem dataItem) {
for (Data data : dataItem) {
if (data.getType() == DataType.BOOLEAN) {
// Convert to String to boolean and save
}
else if (data.getType() == DataType.DOUBLE) {
// Convert to String to double and save
}
...
}
}
但它不是一个非常好的设计,因为我必须为每个save实现重复这个代码。它也违反了开放/封闭原则,因为如果我添加一些新类型,我将不得不修改所有保存方法。
我也尝试过使用泛型或反射,但这些实现都没有令人满意。
我想出的一个通用解决方案要求用户使用提供的枚举常量之一,然后不是存储枚举常量,Data类将存储相应类型的Class实例。这样我就可以控制可以使用的类型,并在选择错误的类时获得编译时错误。这将允许我实现以这种方式工作的转换器方法。
public <T> T convert(Data data, Class<T> clazz) {
if (data.getType() == Boolean.class) {
// Convert String to Boolean
return (T)
}
else if (data.getType() == Double.class) {
// Convert to String to Double
return (T)
}
...
}
然后我还可以在DataType枚举中使用类似的模式和存储转换方法以及允许的数据类型。使用每种类型必须指定的抽象方法。类似的东西:
public enum DataType {
BOOLEAN(Boolean.class){
@Override
public <T> T convert(Data data, Class<T> clazz) {
return clazz.cast(Boolean.parseBoolean(data.getContent()));
}
},
DOUBLE(Double.class){
@Override
public <T> T convert(Data data, Class<T> clazz) {
return clazz.cast(Double.parseDouble(data.getContent()));
}
},
...;
...
public abstract <T> T convert(Data data, Class<T> clazz);
}
在这种情况下,我只需要在添加新类型时修改DataType枚举,前提是底层存储具有接受所有允许类型的方法。
最后,我的问题: 1.有更好的方法吗? 2.如果不是,我应该选择哪种设计?
答案 0 :(得分:0)
您可以创建一个接口(Savable),每个可保存的类需要使用名为toSaveString和initFromSaveString的2个接口函数来实现。
然后,当从DB加载时,您只需要switch语句来确定将数据加载到哪个类。
答案 1 :(得分:0)
您可以将转化功能存储在Map<Class<?>,Function<String,?>>
地图中。根据{{1}}查找转化函数。在创建新类型时向地图添加新功能。
Class
或者,您可以创建自己的Map<Class<?>,Function<String,?>> map = new HashMap<>();
<T> T convert(String data, Class<T> clazz) {
return (T) map.get(clazz).apply(data);
}
类,并为每种类型创建 singleton 实例,并为每个单例添加适当的转换方法:
DataType
您可以根据需要向public abstract class DataType<T> {
<T> T fromString(String data);
}
public final static DataType<Boolean> BOOLEAN = new DataType<Boolean>() {
Boolean fromString(String data) {
...
}
};
// ...
Data data = ...
Object value = data.getType().fromString(data.getContent())
添加其他字段和方法。