用于将字符串转换为Java中不同类型的好设计
我有一个类以字符串形式存储单个数据的数据,它还存储此数据应该转换到的类型,类型存储为枚举常量(仅允许specyfic类型)。描述一个项目的数据对象存储在DataItem类中。意图是Data对象对应于表中的一个字段,DataItem表示一个完整的行。还有一点很重要,即Data对象是从DataTemplate类创建的,它指定在哪里查找这种数据及其类型(因此每个Data的类型应该在编译时知道)。用于将字符串转换为Java中不同类型的好设计
我希望这个程序在数据库选择时非常灵活,所以方法“save”来自Storage接口,它允许在实现它之后使用任何类型的存储(文件/ RDB/Document数据库...)。
我想知道将这些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
}
...
}
}
但它不是一个很好的设计,因为我将不得不重复这个代码保存的每个实行。它也违反了开放/封闭的原则,因为如果我添加一些新的类型,我将不得不修改所有的保存方法。
我也尝试过使用泛型或反射,但没有一个实现令人满意。
我想出了一个通用的解决方案,要求用户使用提供的枚举常量之一,但不是存储枚举常量,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);
}
在这种情况下我只是有添加新类型时修改的数据类型枚举,条件是基础存储具有接受所有允许的类型的方法。
最后,我的问题: 1.有没有更好的方法来做到这一点? 2.如果不是,我应该选择哪种设计?
您可以将您的转换函数存储在Map<Class<?>,Function<String,?>>
地图中。根据Class
查找转换函数。随着新类型的创建,向地图添加新功能。
Map<Class<?>,Function<String,?>> map = new HashMap<>();
<T> T convert(String data, Class<T> clazz) {
return (T) map.get(clazz).apply(data);
}
或者,你可以创建自己的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())
您可以添加额外的属性和方法根据情况适用于DataType
。
我的理解正确吗,getType()方法会返回一个实现的DataType实例吗?如果是这种情况,我应该期望用户从某种集合中选择其中一个实例作为指定Data的类型的形式,而不是提供类
是的,就像你在使用if(data.getType()== DataType.BOOLEAN)时必须选择'DataType'枚举的一个实例一样。它们不需要存储在一个集合中,尽管它们可能是。 (如果'Class >'和'DataType'之间有1对1的映射关系,那么'Data'就可以存储这个类。) – AJNeufeld
您可以创建一个Interface(Savable),每个可保存的类需要使用2个接口函数(称为toSaveString和initFromSaveString)来实现。
然后,当从数据库加载时,您只需要使用switch语句来确定要将数据加载到哪个类。
我很抱歉,如果我没有清楚解释这一点,数据对象的目的是存储数据,因此它可以在保存到数据库之前分离到DataItems中,它将从其他资源获取输入。 –
您可以使用** Integer.toString **,** Double.toString **等 – 0ddlyoko
为什么不能使用Java的强类型系统开始?你的数据来自哪里?或者你在实现某种对象关系映射器吗? –
@ 0ddlyoko toString方法将其他类型转换为字符串我想将字符串转换为其他类型 –