处理表行数据结构的最佳模式是什么?
事实
我有以下数据结构,由一个表和一个属性列表(简化)组成:
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
因非常不同的职责而过载。
替代
方案 感觉 访问者模式 可以做到这一点相反,工作得很好,但另一方面,对于这个简单的结构来说,它看起来有点矫枉过正。
问题
解决这个问题最优雅的方法是什么?
The Facts
I have the following datastructure consisting of a table and a list of attributes (simplified):
class Table {
List<Attribute> m_attributes;
}
abstract class Attribute {}
class LongAttribute extends Attribute {}
class StringAttribute extends Attribute {}
class DateAttribute extends Attribute {}
...
Now I want to do different actions with this datastructure:
- print it in XML notation
- print it in textual form
- create an SQL insert statement
- create an SQL update statement
- initialize it from a SQL result set
First Try
My first attempt was to put all these functionality inside the Attribute
, but then the Attribute
was overloaded with very different responsibilities.
Alternative
It feels like a visitor pattern could do the job very well instead, but on the other side it looks like overkill for this simple structure.
Question
What's the most elegant way to solve this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我会考虑使用 JAXB 和 休眠。
JAXB 允许您对 XML 进行编组和解组。默认情况下,属性将转换为与属性同名的元素,但这可以通过 @XmlElement 和 @XmlAttribute 注释进行控制。
Hibernate(或 JPA)是将数据对象移入和移出数据库的标准方法。
I would look at using a combination of JAXB and Hibernate.
JAXB will let you marshall and unmarshall from XML. By default, properties are converted to elements with the same name as the property, but that can be controlled via @XmlElement and @XmlAttribute annotations.
Hibernate (or JPA) are the standard ways of moving data objects to and from a database.
命令模式浮现在脑海中,或者是一个小的它的变异。
您有很多类,每个类都专门用于对您的数据类执行特定操作。您可以将这些类保存在哈希映射或其他一些结构中,外部选择可以选择一个来执行。为了完成你的任务,你可以使用你的数据作为参数来调用所选命令的execute()方法。
编辑:详细说明。
在底层,您需要对数据行的每个属性执行一些操作。
这确实听起来像访问者模式的一个例子:访问者模拟一个双
调度操作,只要您能够组合变量“受害者”对象
将变量“操作”封装在方法中。
您的属性都需要进行 xml 编辑、文本编辑、插入更新和初始化。
所以你最终会得到一个 5 x 3 类的矩阵来执行这 5 个操作中的每一个
3 个属性类型中的每一个。访客模式的其余部分
将为您遍历您的属性列表并为您应用正确的访问者
您为每个属性选择正确方式的操作。
编写 15 个类加上接口听起来确实有点繁重。你可以这样做
并且有一个非常通用和灵活的解决方案。另一方面,在当时的情况下
你花了很多时间思考解决方案,你可以将代码拼凑在一起
其目前已知的结构,并祈求形状
你的课程不会经常改变太多。
我认为命令模式是为了在各种类似的命令中进行选择
运营。如果要执行的操作作为字符串传入,也许是在
脚本或配置文件等,然后您可以从
...中获得一个映射,其中每个命令都会启动适当的访问者来执行操作
工作。但由于操作更有可能在代码中确定,您可能
不需要这个。
The Command pattern comes to mind, or a small variation of it.
You have a bunch of classes, each of which is specialized to do a certain thing with your data class. You can keep these classes in a hashmap or some other structure where an external choice can pick one for execution. To do your thing, you call the selected Command's execute() method with your data as an argument.
Edit: Elaboration.
At the bottom level, you need to do something with each attribute of a data row.
This indeed sounds like a case for the Visitor pattern: Visitor simulates a double
dispatch operation, insofar as you are able to combine a variable "victim" object
with a variable "operation" encapsulated in a method.
Your attributes all want to be xml-ed, text-ed, insert-ed updat-ed and initializ-ed.
So you end up with a matrix of 5 x 3 classes to do each of these 5 operations
to each of 3 attribute types. The rest of the machinery of the visitor pattern
will traverse your list of attributes for you and apply the correct visitor for
the operation you chose in the right way for each attribute.
Writing 15 classes plus interface(s) does sound a little heavy. You can do this
and have a very general and flexible solution. On the other hand, in the time
you've spent thinking about a solution, you could have hacked together the code
to it for the currently known structure and crossed your fingers that the shape
of your classes won't change too much too often.
Where I thought of the command pattern was for choosing among a variety of similar
operations. If the operation to be performed came in as a String, perhaps in a
script or configuration file or such, you could then have a mapping from
...where each of those Commands would then fire up the appropriate Visitor to do
the job. But as the operation is more likely to be determined in code, you probably
don't need this.
我不知道为什么你现在要自己将数据存储在数据库中,而不是仅仅使用 hibernate,但这是我的调用:
LongAttribute
、DateAttribute
、StringAttribute
,...都有不同的内部结构(即特定于它们的字段不存在于 Attribute 类中),因此您无法创建一种通用方法来序列化它们。现在,XML、SQL 和纯文本在序列化时都具有不同的属性。您确实无法避免编写 O(#subclasses ofAttribute
#output formats)* 不同的序列化方法。Visitor 对于序列化来说是一个不错的模式。确实,如果在非递归结构上使用它有点过大,但是随机程序员阅读您的代码将立即掌握它在做什么。
现在,对于反序列化(从 XML 到对象,从 SQL 到对象),您需要一个工厂。
还有一点提示,对于 SQL 更新,您可能希望有一些东西可以获取对象的旧版本、对象的新版本,并仅根据它们之间的差异创建更新查询。
I dunno why you'd store stuff in a database yourself these days instead of just using hibernate, but here's my call:
LongAttribute
,DateAttribute
,StringAttribute
,… all have different internals (i.e. fields specific to them not present in Attribute class), so you cannot create one generic method to serialize them all. Now XML, SQL and plain text all have different properties when serializing to them. There's really no way you can avoid writing O(#subclasses ofAttribute
#output formats)* different methods of serializing.Visitor is not a bad pattern for serializing. True, it's a bit overkill if used on non-recursive structures, but a random programmer reading your code will immediately grasp what it is doing.
Now for deserialization (from XML to object, from SQL to object) you need a Factory.
One more hint, for SQL update you probably want to have something that takes old version of the object, new version of the object and creates update query only on the difference between them.
最后我使用了访客模式。现在回想起来,这是一个不错的选择。
In the end, I used the visitor pattern. Now looking back, it was a good choice.