2017-09-25 36 views
1

我有一个类以字符串形式存储单个数据的数据,它还存储此数据应该转换到的类型,类型存储为枚举常量(仅允许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.如果不是,我应该选择哪种设计?

+0

您可以使用** Integer.toString **,** Double.toString **等 – 0ddlyoko

+0

为什么不能使用Java的强类型系统开始?你的数据来自哪里?或者你在实现某种对象关系映射器吗? –

+0

@ 0ddlyoko toString方法将其他类型转换为字符串我想将字符串转换为其他类型 –

回答

0

您可以将您的转换函数存储在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

+0

我的理解正确吗,getType()方法会返回一个实现的DataType实例吗?如果是这种情况,我应该期望用户从某种集合中选择其中一个实例作为指定Data的类型的形式,而不是提供类的实例? –

+0

是的,就像你在使用if(data.getType()== DataType.BOOLEAN)时必须选择'DataType'枚举的一个实例一样。它们不需要存储在一个集合中,尽管它们可能是。 (如果'Class '和'DataType'之间有1对1的映射关系,那么'Data'就可以存储这个类。) – AJNeufeld

0

您可以创建一个Interface(Savable),每个可保存的类需要使用2个接口函数(称为toSaveString和initFromSaveString)来实现。

然后,当从数据库加载时,您只需要使用switch语句来确定要将数据加载到哪个类。

+0

我很抱歉,如果我没有清楚解释这一点,数据对象的目的是存储数据,因此它可以在保存到数据库之前分离到DataItems中,它将从其他资源获取输入。 –

相关问题