“价值”会员字段可以是四种不同类型之一 - 最佳设计?

时间:2010-01-13 13:43:34

标签: java design-patterns model

我有一个名为“DataModel”的类,它基本上是一个数据单元,可以是字符串,数字或日期,也可以是具有各种(相同)属性的布尔值。

编写此模型的最佳方法是什么?

  1. 值的类型为Object

    interface DataModel {
       Object getValue();  // cast to whatever is needed
       int getValueType(); // uses four constants
    }
    
  2. 有四种不同的实现“StringModel”,“NumberModel”等,每种都有自己的类型“getValue()”方法。这意味着如果您有一个DataModel,则必须转换为正确的Model才能获得该值。

    interface DataModel {
       int getValueType();
    }
    interface NumberDataModel extends DataModel {
      Integer getValue();
    }
    ...
    
  3. 有四种不同的方法,如果调用错误的值类型,每种方法都会抛出异常:

    interface DataModel {
      String getStringValue();
      Integer getIntegerValue();
      ...
      int getValueType();
    }
    
  4. 使用泛型。这有一个缺点,我理论上可以有任何类型的任何对象...另一方面,如果T不是4种允许类型之一,我可以在构造函数中抛出IllegalStateException ...

    interface DataModel<T> {
      T getValue();
    }
    
  5. 没关系。以上任何一种。 ;)

5 个答案:

答案 0 :(得分:3)

4似乎是最好的 - 即使你不想实现任何旧类型,也没有特别的理由为什么你理论上不允许它 - 它不会干扰你正在做的任何事情。

答案 1 :(得分:2)

如果您不打算添加许多/任何新类型并且您不需要允许第三方添加他们自己的类型,那么

1就可以了。我可能会使用枚举而不是int。

我没有看到做2超过4的优点.4是通用的,你可能想要包括getValueType(),即使在通用情况下,这样你就可以让代码在运行时询问类型,通常很有用。

我不认为3是正确的方法,除非你的模型的内容支持以不同的方式检索(比如JDBC在某种程度上),但我不认为这是这种情况。

根据过去的经验,我会做4并将getValueType()添加到它。

答案 2 :(得分:2)

以上都不是。

由于您需要知道类对getValue()的结果做了一些合理的事情,因此在这种情况下,使用包含getValue()的公共接口(类似于方法)没有任何好处。

有一个带有公共部分的基类,然后继承并添加你需要的东西。您可以使用instanceof而不是getValueType(),但如果您确实需要getValueType,则可以将其作为抽象方法添加到基类中。如果你使用getValueType,我建议它返回一个枚举,而不是int。

答案 3 :(得分:2)

4是最好的答案。您将获得灵活性和便利性。

另一方面,如果你真的想限制类型,你可以使用4和2的组合。像这样:

interface DataModel<T> {
   T getValue();
}
interface NumberDataModel extends DataModel<Number> {
   // empty
}
class NDM implements NumberDataModel {
   Number getValue() { return ... }
}

然后,您可以使DataModel接口受保护/默认。

答案 4 :(得分:0)

作为一种通用替代方法,您可以使用Class Literals as Runtime-Type Tokens并使用newInstance()来获取数据元素的类型安全实例。这允许通过通用参数进行编译时检查,并通过isAssignableFrom()进行运行时检查。