2013-12-13 37 views
2

我有,我有有5场与getter和setter方法模式的情况下,说ID,姓名,年龄,出生日期,城市字符串或枚举作为参数来引用示范田

服务类包含一个绑定的方法,它只返回数组形式的特定字段数据。就像我只想要所有人的名字和年龄。

List<Object> getEmpDataAsList(List<Object> fields); 

所以,我的方法是这样的,其需要一个参数fields其包含了需要被返回的字段列表。因此,对于这种情况,我应该只发送nameage字段参数,我的getEmpDataAsList检测字段要求并相应地构建返回数组。

我想知道做这件事的最好方法是什么。我应该通过fields列表作为字符串,我也做目前,如:

List<String> fields = new ArrayList<>(); 
fields.add("name"); 
fields.add("age"); 

getEmpDataAsList(fields); 

但是我想,这是不是安全的。如果我计划一天改变一个领域的名字,或者如果我从模型中删除一个领域,那么我需要在3个地方进行更改。我应该在模型类中创建枚举并使用枚举字段创建这个相同的数组并使用它?或者还有其他更好的方法吗?

+0

服务'getEmpDataAsList(列表)'给出或允许改变它吗? –

+0

@Chris Ya我对项目有完整的权利,我可以随时更改它。 – Abhi

回答

1

,如果我打算更改字段一天或什么的名字,如果我从模型中删除 场,然后我需要在3个地方进行更改。

这个问题没有解决办法。如果你删除了一个字段,它就消失了。你必须从模型和客户端中删除它。但是,这是一个快速的解决方案,可以使更改变得明显,以便更改API会导致编译错误。

在一个抽象的父类使用泛型检查参数列表在编译:

public abstract class GenericDataInterface<KEY extends Enum> { 
    public abstract Object getData(KEY key); 

    public final List<Object> getEmpDataAsList(List<KEY> fields) { 
     List<Object> result = new ArrayList<Object>(fields.size()); 
     for (KEY field : fields) { 
      result.add(getData(field)); 
     } 
     return result; 
    } 
} 

例模型类:

public class Pizza extends GenericDataInterface<Pizza.PizzaAttributes> { 
    public enum PizzaAttributes { NAME, TOPPINGS, PRICE }; 

    private String name; 
    private Set<String> toppings; 
    // WARNING: Do not use Float for prices in real applications! 
    private float price; 

    @Override 
    public Object getData(PizzaAttributes key) { 
     switch (key) { 
      case NAME: 
       return name; 
      case TOPPINGS: 
       return toppings; 
      case PRICE: 
       return price; 
      default: 
       throw new IllegalArgumentException(
         "Key " + key + " isn't defined for " + Pizza.class.getCanonicalName()); 
     } 
    } 
} 

结果是不是很方便呢,因为扭曲会导致不可见的问题。因此,你可以使用Map作为结果

public abstract class GenericDataInterface<KEY extends Enum> { 
    public abstract Object getData(KEY key); 

    public final Map<KEY, Object> getEmpDataAsList(List<KEY> fields) { 
     Map<KEY, Object> result = new HashMap<KEY, Object>(fields.size()); 
     for (KEY field : fields) { 
      result.put(field, getData(field)); 
     } 
     return result; 
    } 
} 

不是地图,你也可以使用真实模型类的克隆,只填写指定的属性。

另外的想法:

  • 你真的需要这样的通用接口?
  • 如果是关于网络通信,你不能使用XML或JSON吗?
+0

你不应该使用'KEY extends Enum'的原始类型。要么输入它的东西,要么将其保留为未知的'枚举',但不是原始类型。 – Bohemian

+0

@Bohemian:为什么?无论如何你永远不会从Enum手动继承。 –

+2

,因为Enum是泛型类。绑定到枚举的正确方法是'>' – Bohemian

1

您应该为不同的字段类型使用枚举。 (虽然,我不知道是否需要AGE和DOB,因为您可以从当前日期和DOB计算年龄......)

public enum Fields{ 
    NAME, 
    DOB, 
    CITY 
    ... 


} 

这样你可以有更多的意图揭示API。

List<Object> getEmpDataAsList(Fields...fields) 

List<Object> getEmpDataAsList(Set<Fields> fields) 

这将让你去做

results = getEmpDataAsList(Fields.AGE, Fields.DOB); 

results = getEmpDataAsList(EnumSet.of(Fields.AGE, Fields.DOB)); 

的事情,如果你有过我会建议API总量控制也将List的返回类型更改为地图,这样你就可以知道哪个字段的值是不知道或关心输入字段顺序的。

Map<Fields,Object> getEmpData(Fields...fields) 

如果我打算更改字段一天或什么的名字,如果我从模型中删除字段,然后我需要在3个地方进行更改。

使用枚举,如果您重命名枚举,则IDE可以为您自动重命名所有引用。如果你删除一个枚举,你会得到一个编译器错误,所以你知道需要改变什么。

+0

非常感谢,我非常喜欢这种简单性,我将在我目前的情况下使用它的大部分:) – Abhi