Java反模式名称是什么?包含对象的对象等等...

8
有没有一种名称或特定规则来描述包含其他对象的对象,以此类推。我正在处理一个复杂的系统,其中经常有五到十层深的对象运行。听说这样做的一个原因是为了一次性从服务器传递大量数据到客户端,是否有更好的方法来解决这个问题?
编辑:看起来它是几种反模式的组合。领域模型应该被清理,以下反模式是问题所在:火车失事模式和除了厨房水槽映射之外的所有内容

1
我不知道这是否是反模式。如果你看任何ORM,你会发现包含着其他bean的bean... - SJuan76
2
代码层级太多就被称为“千层饼代码” :) - Adam Stelmaszczyk
1
我们有一个名为“责任链模式”的设计模式,适用于上述场景。只要一个实体负责处理它下面的下一个实体即可。- http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern - Rockstart
4个回答

7
我不知道这种对象树的名称。但是一个众所周知的反模式是“火车失事模式”,当代码使用过多的方法链时会出现这种情况。
objA.getChildB().getChildC().getChildD()....getChildZ().performSomeAction();

通常最好的做法是将所有的

.getChildC().getChildD()....getChildZ().performSomeAction();

将其转换为方法参数。
objA.getChildB()

我们把这个方法称为 performSomeActionDeepDownTheObjectTree()


如果调用量增加,这样做会不会导致childB中出现不必要的膨胀?创建一个包含所需对象的特定数据对象,并将调用添加到该对象中以封装逻辑可能会更好。 - FooBar
1
@FooBar 你可以这样做。如何解决由这种反模式引起的问题留给读者自己练习 :) - user647772
如果我不能更改A、B、C..Z中的任何方法/类,该怎么办? - Quirk

5
这似乎是一个出问题的领域模型(顺便说一下,这不是反模式名称 :)),它源于这样一个错觉:存在所谓明确定义的领域模型。事实上,在问题领域中有一些方面可以优雅地建模,但在更细节的层面上,有许多例外和特殊情况,每个特定于单个服务方法,破坏了这种优雅。
经常出现许多嵌套对象的原因是将领域模型不断“磨细”到越来越小的颗粒度,希望每个实例变量都可以在不同的上下文中重用。但是随着狗matic强制要求重复使用每个领域属性的突破点到来,这种做法就不再有意义。
我的解决方法是停止尝试创建适合所有情况的领域模型,并为每个服务调用使用专门设计的对象。这些对象可以依赖于一些明确定义的领域对象,但会单独添加任何特定信息,并以不干扰其他服务调用的方式添加。

听起来是个不错的解决方案,我得看看领域模型,看看能否清理一下并实现一些新的特定对象,以避免这种情况。 - FooBar

3
术语是“面向对象”,它通过定义对象类将大型复杂问题分解为较小的问题,每个对象封装了问题的一小部分。对象相互交互的方式是通过消息传递,并且对象通过从它们包含的对象开始查找其他对象来传递消息。
问题越大、越复杂,你需要做更多的工作来将其分解成可管理的部分,因此你会得到更多层次的对象。有时候,简单的小问题被分解成大量对象,但这并不意味着面向对象本身是一种反模式。
主要问题在于数据对象通过嵌套以及包含不相关的数据变得过于庞大。例如:您正在对鸟进行排序,而不是简单的鸟对象,您收到一个包含羽毛、喙、可能寄生物、空气、可能的巢穴和食物类型的鸟对象,食物类型包含水果、昆虫、蠕虫、种子,种子包含橡树、榆树、蓟、可能吃种子的动物等等。 除了厨房水槽地图 反模式可能是最接近的匹配。
给定一个具有许多复杂规则的复杂流程,所有内容(业务逻辑、相关和无关程序等)都被塞进了地图中。
解决这个问题的最佳方法是使用过滤操作,其中您指定一个强类型接口,例如 interface BirdList extends Iterable<Bird> {},并且查询系统提供该接口的实现,由足够支持该接口的数据支持。
你的API可以提供许多不同的接口,例如 BirdListBirdFeedingHabitMapBirdNestingHabitMap等。客户端可以列出他们需要的接口,查询系统会分析它们,获取数据,并使用代理类来组装一个实现类,以类型安全的方式公开查询结果。

当然,我不是在争论这个问题,我说的是当你有对象时,特别是数据对象嵌套到第n层,会导致数据膨胀,并且很难访问正确的数据,甚至在检索对象时也不知道包含哪些数据。 - FooBar
虽然这可能是一个问题,但并不是主要问题,主要问题是数据对象通过嵌套以及包含无关数据而变得过于庞大。例如:你正在对鸟进行排序,而不是简单的鸟类对象,你收到了一个包含羽毛、喙、可能的寄生虫、空气、可能的巢穴和食物类型的鸟类对象,食物类型包括水果、昆虫、蠕虫、种子,种子包括橡树、榆树、蓟草、可能吃种子的动物等等。 - FooBar
@FooBar,这些数据是否通过网络发送?你是否可以说——我需要满足这个接口的东西,并且只想要满足这个接口所需的数据? - Mike Samuel
@FooBar,请看我的编辑。"除了厨房水槽地图"反模式描述了你所说的内容。 - Mike Samuel
是的,我认为这是对发生情况的很好描述,我认为你找到了正确的反模式。但是对于解决方案,我认为我的需求将是上面建议的清理域,通过修剪对象并为超出其范围的情况创建自定义对象来实现。 - FooBar

2
“包含对象,再包含对象……等等”被称为列表,非常好;但是您说得对,长序列的方法调用并不好,这是一种代码规范问题,称为“不恰当亲密关系”。
“不恰当亲密关系”可能会增加耦合度,降低内聚力,违反了“德米特法则”,以及“告诉,不要问”的规则。
参考资料:如果您查阅这些术语,您会发现有无数多的答案。特别好的是Cohesion and CouplingAgile Software Development, Principles, Patterns, and Practices by Robert C. Martin这本书。

2
我认为那不叫做“列表”。列表是关于事物相邻的。 - user647772
这是一个Object列表 - 但它更多是作为一个玩笑,因为包含对象的对象是完全可以的,只是长串的方法调用不太好。希望我的回答能澄清这一点。 - DaveFar
一个 House 对象可以包含一个 Door 对象,该对象可以包含一个 Lock 对象,该对象可以包含一个 KeyHole 对象,依此类推。这是层次结构而不是列表。 - jlordo
@jlordo:...它们都是Object类型的。 - DaveFar
OP没有提及对象的类型。 - jlordo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接