我刚刚开始了一个让我的雇主成为管理软件的项目。我有一个琐碎,但可能很简单的查询,我似乎无法找到任何信息。
在对象之间建立双向'关系'是谨慎/良好的做法吗?例如,Client
对象'可以有'Site
,然后Site
'有'Client
,其中Client
对象是Client
“有'Site
?
public class Client {
Site site;
}
public class Site {
Client client;
}
这有什么令人反感的(没有双关语意),还是没事?我目前正在为该项目创建一个模拟UML,这一直困扰着我。
答案 0 :(得分:3)
这有什么不妥之处,还是没事?
对此没有明确的答案。最好的答案是:它取决于您的应用程序的设计。
何时使用
如果您的Client
对象应导航到Site
对象,并且您的Site
对象应导航到Client
对象,那么代码中的当前示例就可以了。尽管如此,您可能还需要一些方法来关联这些元素,可能是通过其中一个类或两个类中的附加id字段。
如果您使用的框架可以帮助您像Hibernate一样自动绑定类,那么维护循环引用对您来说不是问题。
何时不使用
基本上,对于文本序列化,因为它会生成无限循环。正如Raibaz's answer中已经提到的,像Jackson这样的库会在将Client
或Site
类序列化为JSON字符串 1 时陷入无限循环。请注意,在序列化为其他String
数据时,这也是有效的,例如通过XML中的JAX-WS Web服务传递对象(更多信息:What happens to generic class in jax-ws webservice?)。
1 这可以使用属于特定库的注释(@Something
)来解决,例如正如@SimonAndréForsberg所指出的那样,来自Jackson library的@JsonManagedReference
和@JsonBackReference
,但此解决方案的缺点是您的类将与库紧密耦合。
答案 1 :(得分:2)
这很常见,但我会考虑你希望子对象与其父对象的松耦合程度。如果您从子对象引用了父对象,那么您将无法将该对象与另一个父对象/无父对象重用。
答案 2 :(得分:1)
在对象之间建立共同的关联是很常见的。
例如,在某些用户界面工具包中,可视组件将引用其子组件,并且每个子组件都可以引用其父组件。
术语 has-a 经常用于将一个对象的所有权与另一个对象进行通信。如果这是真的,这种关系通常是单向的。
Booch,Rumbaugh和Jacobson在“统一建模语言用户指南”中提供了这些术语的一个很好的定义:
聚合 - 两个类之间的普通关联表示对等体之间的结构关系,这意味着两个类在概念上处于同一级别,没有一个比另一个更重要。有时候,你会想要建立一个“整体/部分”关系,其中一个类代表一个更大的东西(“整体”),它由较小的东西(“部分”)组成。这种关系称为聚合,它表示“has-a”关系,这意味着整个对象具有该部分的对象。
答案 3 :(得分:1)
与你的例子中的双向关联一样,这很常见且很常见。
您可能要考虑的唯一警告是当您要序列化对象时,例如在使用Jackson或任何其他库的json中,您应该排除关联的两个方面中的一个从序列化以避免以无限循环。
答案 4 :(得分:1)
我会尽可能地坚持单向关系。双向关系使两个类绑在一起,其中一个更改导致另一个更改两个。问问自己这种关系是否真的很自然......
如果必须,只需确保两个接口或至少其中一个是接口。