1

我正在编写一个包含一堆类的程序,这些类将被序列化以保存在数据库中并通过网络发送。

为了使通过命令行界面访问类属性更容易,我正在考虑将属性存储在 Map 类中,而不是为每个属性提供它自己的变量。

基本上,而不是使用这样的东西:

String id = account.getUserId();

我会这样做

String id = account.properties.get("userId");

这是一种可取的做事方式吗?

4

2 回答 2

2

我喜欢这样做的方式通常是这样的:

enum StringPropertyType {
   USERID, FIRSTNAME, LASTNAME
}

interface StringAttributes {
    String get(StringPropertyType s);
    void put(StringPropertyType s, String value);
}

class MapBasedStringAttributes implements StringAttributes {
    Map<StringPropertyType, String> map = new HashMap<~>();
    String get(StringPropertyType s) { return map.get(s); }
    void put(StringPropertyType s, String value) { map.put(s,value); }
}

这为您提供了编译时安全性、重构等。

您还可以使用 stringPropertyType.name() 来获取枚举值的字符串表示形式并使用

Map<String,String> 

反而..

于 2012-05-18T04:11:01.410 回答
2

是的,这是一个非常明智的模型。它有时被称为“原型对象模型”,与在 JavaScript 中的工作方式非常相似,其中每个对象实际上都是一个 Map。这反过来又导致了非常流行的 JSON 序列化格式。

不错的特点:

  • 您不必担心混乱的继承层次结构 - 您可以随意更改属性。
  • 您可以通过从另一个对象(原型)复制来创建一个新对象
  • 操作数据的代码可以以统一的方式执行此操作,而无需显式命名所有变量。
  • 与静态类定义相比,它更“动态”——扩展和修改对象很容易

潜在风险/不利因素:

  • 如果您使用字符串,则需要跟踪您的属性名称 - 编译器不会为您执行此操作!这个问题可以通过使用枚举作为键来缓解,但是你会失去一些灵活性......
  • 您没有获得静态类型检查的好处,因此您可能会发现需要编写更多的 JUnit 测试以确保一切正常
  • 有轻微的性能开销(尽管可能不足以担心,因为地图查找非常快)

实际上,我在 90 年代使用这个对象模型 ( Tyrant ) 的变体编写了一个完整的游戏,并且效果很好。

但是,您可能需要考虑封装此功能,以便您可以在对象本身上使用访问器方法,而不是暴露 Map 对象,例如

String id = account.getProperty("userId");
于 2012-05-18T04:08:55.160 回答