我自己也一直在考虑这个问题。到目前为止,这是我的松散想法,我想知道其他人的想法。
xAL(及其包含个人姓名的姐妹 XNAL)被 Google 和 Yahoo 的地理编码服务使用,这给了它一定的权重。但是由于可以在 xAL 中以许多不同的方式描述相同的地址——有些方式比其他方式更具体——所以我看不出 xAL 本身是如何成为一种可接受的数据存储格式。然而,它的一些字段名称可以使用,但实际上,在我公司运送到的 16 个国家/地区中唯一可以使用的基本格式如下:
enum address-fields
{
name,
company-name,
street-lines[], // up to 4 free-type street lines
county/sublocality,
city/town/district,
state/province/region/territory,
postal-code,
country
}
这很容易映射到单个数据库表中,只允许在大多数列上使用 NULL。这似乎是亚马逊和许多组织实际存储地址数据的方式。所以剩下的问题是我应该如何在程序员和任何 GUI 代码都可以轻松使用的对象模型中对此进行建模。我们是否有一个基本Address 类型以及每种地址类型的子类,例如AmericanAddress、CanadianAddress、GermanAddress 等等?这些地址类型中的每一个都知道如何设置自己的格式,并且可以选择了解一些关于字段验证的信息。
它们还可以返回有关每个字段的某种类型的元数据,例如以下伪代码数据结构:
structure address-field-metadata
{
field-number, // corresponds to the enumeration above
field-index, // the order in which the field is usually displayed
field-name, // a "localized" name; US == "State", CA == "Province", etc
is-applicable, // whether or not the field is even looked at / valid
is-required, // whether or not the field is required
validation-regex, // an optional regex to apply against the field
allowed-values[] // an optional array of specific values the field can be set to
}
事实上,我们可以采用稍微不那么面向对象的方法,即拥有一个避开 .NET 属性并使用 AddressStrategy 来确定格式和验证规则的 Address 对象,而不是为每个国家/地区创建单独的地址对象,而不是实际上:
object address
{
set-field(field-number, field-value),
address-strategy
}
object address-strategy
{
validate-field(field-number, field-value),
cleanse-address(address),
format-address(address, formatting-options)
}
在设置字段时,Address 对象将调用其内部 AddressStrategy 对象上的适当方法。
使用SetField() 方法而不是使用getter 和setter 的属性的原因是,代码更容易以通用方式实际设置这些字段,而无需求助于反射或switch 语句。
你可以想象这个过程是这样的:
- GUI 代码调用工厂方法或类似方法来创建基于国家/地区的地址。 (因此,国家下拉菜单是客户选择的第一件事,或者根据文化信息或 IP 地址为他们预先选择了一个很好的猜测。)
- GUI 调用
address.GetMetadata() 或类似方法并接收AddressFieldMetadata 结构的列表,如上所述。它可以使用此元数据来确定要显示哪些字段(忽略那些将is-applicable 设置为false 的字段),标记这些字段的内容(使用field-name 成员),以特定顺序显示这些字段,并执行粗略,对该数据进行演示级验证(使用is-required、validation-regex 和allowed-values 成员)。
- GUI 使用
field-number(对应于上面的枚举)及其给定值调用address.SetField() 方法。然后Address 对象或其策略可以对这些字段执行一些高级地址验证、调用地址清理器等。
如果我们想让Address 对象本身在创建后表现得像一个不可变对象,那么上面的内容可能会略有不同。 (我可能会尝试这样做,因为 Address 对象实际上更像是一种数据结构,并且可能永远不会有任何与自身相关的真实行为。)
这些有意义吗?我是否偏离 OOP 路径太远了?对我来说,这代表了在抽象到几乎不可能实现 (xAL) 与严格偏向美国之间的一种相当明智的折衷。
2 年后更新:我最终得到了一个与此类似的系统,并在my defunct blog 上写了这篇文章。
我觉得这个解决方案是遗留数据和关系数据存储之间的正确平衡,至少对于电子商务世界来说是这样。