0

事实

我有以下数据结构,由一个表和一个属性列表(简化)组成:

class Table {
    List<Attribute> m_attributes;
}

abstract class Attribute {}

class LongAttribute extends Attribute {}
class StringAttribute extends Attribute {}
class DateAttribute extends Attribute {}
...

现在我想用这个数据结构做不同的动作:

  • 以 XML 表示法打印
  • 以文本形式打印
  • 创建 SQL 插入语句
  • 创建 SQL 更新语句
  • 从 SQL 结果集中初始化它

第一次尝试

Attribute我的第一次尝试是将所有这些功能放在Attribute.

选择

感觉访问者模式可以很好地完成这项工作,但另一方面,对于这个简单的结构来说,它看起来有点矫枉过正。

问题

解决这个问题的最优雅的方法是什么?

4

4 回答 4

1

想到命令模式,或者它的一个小变种。

您有一堆类,每个类都专门用于对您的数据类执行特定操作。您可以将这些类保存在 hashmap 或其他一些结构中,外部选择可以从中选择一个来执行。为了做你的事情,你调用所选命令的 execute() 方法,并将你的数据作为参数。


编辑:阐述。

在底层,您需要对数据行的每个属性执行一些操作。这听起来确实像是访问者模式的一个案例:访问者模拟了双重调度操作,只要您能够将变量“受害者”对象与封装在方法中的变量“操作”组合起来。

您的属性都希望是 xml-ed、text-ed、insert-ed update-ed 和 initializ-ed。因此,您最终会得到一个由 5 x 3 类组成的矩阵来对 3 种属性类型中的每一种执行这 5 种操作中的每一种。访问者模式的其余部分将为您遍历属性列表,并以正确的方式为您为每个属性选择的操作应用正确的访问者。

编写 15 个类和接口听起来确实有点繁重。你可以做到这一点,并有一个非常通用和灵活的解决方案。另一方面,在您考虑解决方案的时间里,您可能已经将当前已知结构的代码拼凑在一起,并祈祷您的类的形状不会经常改变太多。

我想到命令模式的地方是在各种类似的操作中进行选择。如果要执行的操作以字符串形式出现,可能在脚本或配置文件等中,那么您可以从

"xml" -> XmlifierCommand
"text" -> TextPrinterCommand
"serial" -> SerializerCommand

...然后每个命令都会启动适当的访问者来完成工作。但由于操作更有可能在代码中确定,您可能不需要这个。

于 2009-11-10T07:37:06.130 回答
1

我会考虑使用JAXBHibernate的组合。

JAXB 将让您从 XML 编组和解组。默认情况下,属性被转换为与属性同名的元素,但可以通过@XmlElement 和@XmlAttribute 注释控制。

Hibernate(或 JPA)是将数据对象移入和移出数据库的标准方法。

于 2009-11-10T07:39:07.123 回答
1

我不知道为什么这些天你自己将东西存储在数据库中而不是仅仅使用休眠,但这是我的电话:

LongAttribute, DateAttribute, StringAttribute,... 都有不同的内部结构(即,它们特有的字段不存在于 Attribute 类中),因此您不能创建一种通用方法来将它们全部序列化。现在 XML、SQL 和纯文本在对它们进行序列化时都有不同的属性。确实没有办法避免编写O(#subclasses of Attribute   #output formats)* 不同的序列化方法。

访问者不是一个糟糕的序列化模式。诚然,如果在非递归结构上使用它有点矫枉过正,但随机阅读您的代码的程序员会立即掌握它在做什么。

现在对于反序列化(从 XML 到对象,从 SQL 到对象),您需要一个Factory

还有一个提示,对于 SQL 更新,您可能想要获取对象的旧版本、新版本的对象并仅根据它们之间的差异创建更新查询。

于 2009-11-10T18:43:52.427 回答
0

最后,我使用了访问者模式。现在回想起来,这是一个不错的选择。

于 2010-02-04T16:51:26.793 回答