我认为您不应该将这些属性中的任何一个视为实际的成员变量。您应该有一个包含属性(类似于成员变量)的“Property”对象,以及一个具有属性集合(类似于类)的“Collection”对象。
由于这些属性和集合实际上并没有与之关联的代码,因此将它们作为对象来实现是没有意义的(而且会让人头疼)
您的属性和集合需要保存所有特定于它们的数据。例如,如果一个字段最终被写入数据库,它需要将它的表名存储在某个地方。如果需要将其写入屏幕,则还需要将其存储在某个地方。
范围/值检查可以“添加”到属性中,因此当您定义属性是什么类型的数据时,您可能会有一些文本显示“MaxLength(12)”,它将实例化一个名为 MaxLength 的类,其值为 12,并将该类存储到属性中。每当属性的值更改时,新值将传递给已应用于此类的每个范围检查器。可以有许多类型的动作与该类相关联。
这只是基础。我已经设计了这样的东西,这是一个很好的工作,但它比尝试用一种直接的语言来做要简单得多。
我知道现在这似乎工作太多了(如果你真的明白我的建议,它应该),但请记住它,最终你可能会去“嗯,也许这毕竟值得一试” .
编辑(回复评论):
我考虑过尝试使用注册表/键的东西(我们仍在谈论属性值对),但它不太合适。
您正在尝试将 DAO 放入 Java 对象中。这真的很自然,但我开始将其视为解决 DAO/DTO 问题的一种糟糕方法。Java 对象具有作用于这些属性的属性和行为。对于您正在做的事情,没有行为(例如,如果用户创建一个“生日”字段,您将不会使用目标代码来计算他的年龄,因为您并不真正知道生日是什么)。
因此,如果您丢弃拥有对象和属性,您将如何存储这些数据?
让我先迈出非常简单的第一步(这与您提到的注册表/标签系统非常接近):在您使用对象的地方,使用哈希表。对于您的属性名称,使用键,对于属性值,使用哈希表中的值。
现在,我将介绍我为增强这个简单模型而采取的问题和解决方案。
问题:您丢失了强类型,并且您的数据格式非常自由(这可能很糟糕)
解决方案:为“属性”创建一个基类,以代替哈希表中的值。为 IntegerAttribute、StringAttribute、DateAttribute 扩展该基类...... 不要允许不适合该类型的值。现在你有强类型,但它是运行时而不是编译时——可能没问题,因为你的数据实际上是在运行时定义的。
问题:格式化程序和验证程序
解决方案:能够为您的属性基类创建插件。您应该能够为任何属性“setValidator”或“setFormatter”。验证器/格式化程序应该与属性一起使用——所以当你保存属性时,你可能必须能够将它们序列化到数据库中。
这里好的部分是,当您对属性执行“attribute.getFormattedValue()”时,它会预先格式化以供显示。如果任何验证失败,attribute.setValue() 将自动调用验证器并抛出异常或返回错误代码。
问题:如何在屏幕上显示这些?我们已经有了 getFormatted() 但它在屏幕上的什么位置显示?我们用什么做标签?什么样的控件应该编辑这个字段?
解决方案:我会将所有这些内容存储在每个属性中。(订单应该存储在类中,但由于这是一个哈希表,所以它不会工作——好吧,我们接下来会谈到)。如果您存储显示名称、用于呈现此的控件类型(文本字段、表格、日期...)和数据库字段名称,则此属性应具有与显示和数据库交互所需的所有信息/ O 编写处理属性的例程。
问题:哈希表对于 DAO 来说是一个糟糕的接口。
解决方案:这是完全正确的。您的哈希表应该包装在一个知道它所拥有的属性集合的类中。它应该能够将自己(包括它的所有属性)存储到数据库中——可能在帮助类的帮助下。它应该能够通过单个方法调用来验证所有属性。
问题:如何实际使用这些东西?
解决方案:由于它们包含自己的数据,因此在系统中它们交互的任何位置(例如与屏幕或数据库),您都需要一个“适配器”。
假设您正在展示一个屏幕来编辑您的数据。您的适配器将被传递一个框架和一个基于哈希表的 DTO。
首先,它会按顺序遍历属性列表。它会询问第一个属性(比如一个字符串)它想使用什么样的控件来进行编辑(比如一个文本字段)。
它将创建一个文本字段,然后将一个侦听器添加到将更新数据的文本字段,这会将您的数据绑定到屏幕上的控件。
现在,每当用户更新控件时,更新都会发送到 Attribute。该属性存储新值,您就完成了。
(这会因为一次传输所有值的“OK”按钮的概念而变得复杂,但我仍然会事先设置每个绑定并使用“OK”作为触发器。)
这种绑定可能很困难。我是手工完成的,一旦我使用了一个名为“JGoodies”的工具包,它内置了一些绑定能力,这样我就不必自己编写每个可能的绑定组合,但我不确定从长远来看它节省了很多时间。
这太长了。总有一天我应该创建一个 DAO/DTO 工具包——我认为 Java 对象根本不适合作为 DAO/DTO 对象。
如果您仍然感到困惑,请随时通过电子邮件/即时消息给我——gmail 的 bill.kress。