对象内的链接是否被视为反模式?

时间:2011-05-23 14:24:00

标签: c# java language-agnostic linked-list class-design

假设您有一个经常(甚至独占)的类用作链接列表的一部分。将链接信息放在对象中是反模式吗?

例如:

   public class Item
   {
       private Item prev; 
       private Item next;
       ...
   }

经常被引用的建议是简单地使用通用容器类(例如Java中的java.util.LinkedList),但是这会产生具有单独节点对象的开销(并且链接对象不能容易地引用其兄弟姐妹) )。

思想?

8 个答案:

答案 0 :(得分:2)

我是这么认为的。在我看来,你正在混合责任(例如,如果你的对象反映了员工,我希望只看到与员工相关的属性和方法,而不是与链表相关的方法和属性。)

有时一点点开销就是拥有“更清洁”设计的成本。你是否愿意支付这笔费用是一个不同的问题。在我看来,使用内置链表等实用程序所增加的小开销是值得的...它节省了开发时间,经过全面测试并使设计更加简洁。

答案 1 :(得分:2)

如果链接列表中没有使用 始终 ,这是一种反模式。如果您向可能需要的课程添加属性/方法,您最终将获得瑞士军队。阅读YAGNI

添加这些方法也会破坏SRP,因为该项目还将负责跟踪它的兄弟姐妹。

答案 2 :(得分:2)

一般情况下,这是一种推荐使用方式,因为将来您需要的功能可能会逐渐消失。即使您目前不需要“搜索”和“排序”等功能,有一天规格也会发生变化,您需要对商品进行排序。如果以这种方式实现它,现在需要实现排序。

包含的链接列表存在,因为它们已经过试用,信任和调试。为这些编写自己的函数只是复制了许多不必要的工作。

此外,您担心额外对象节点的开销不应该太担心 - 它可能会带来多少额外开销?在今天这样的日子里,即使它们是一个千字节(这将是疯狂),它也不应该让人担心。

答案 3 :(得分:2)

它不一定是反模式。反模式必须具有负面的副作用才能获得“反”的权利。

例如,Node数据结构中的Tree 需要它在Node内缓存的链接。任何其他东西都会违反更重要的基于对象责任的数据和代码封装和本地化概念。

另一方面,Customer数据结构嵌入了" next"客户意味着Customer数据结构正在处理两个不相关的职责,即维护Customer数据,以及维护Customer列表数据结构的职责。在这种情况下,这两项责任可能会以影响维护方便性的方式混合在一起;因此,将被视为一种反模式。

答案 4 :(得分:2)

我相信java中的XML DOM类(你喜欢什么),所以它至少有先例。通常你所描述的可能是例外,而不是规则,否则你最终会重新实现一个链表。

答案 5 :(得分:1)

在Java中,它比其他语言更少问题,因为Item必须是类指针。另一方面,如果Item是一个结构,就像C#和其他语言一样,你会遇到明显的问题。除了你有一个可变结构的事实,你也可能会遇到一个编译时错误,试图定义一个具有无限大内存需求的结构。

根据要求,允许对象通过next和previous引用其兄弟姐妹可能要简单得多,层次结构中的对象通常可以通过引用它来引用它的父级。

答案 6 :(得分:1)

此模式称为侵入式容器

在每种情况下都不是正确的做法,但它有一些众所周知的优点(内存使用率更低,局部性更好,内存管理器分配和收集的对象更少)。

答案 7 :(得分:1)

与往常一样,取决于项目的范围和/或使用它的上下文。如果项目规模相当小,那么遵循每一项良好实践指南都不会对您有所帮助:您最终会花费更多时间“正确”地完成这项工作,而且收益可能几乎为零。

如果您的项目有点大,但此链接列表仅在本地使用,例如在单个源文件中,或作为类的私有成员(换句话说,如果它是实现细节,而不是总体机制),那么你也可以跳过“正确”并采取更简单的方法。

只有当项目很大并且链表是拼图的重要部分时,您才应该花时间尽可能完美地完成它。根据经验,如果多个源文件需要此链接列表,那么请正确执行,不要偷工减料。

一般来说,知道何时以及如何消耗能量。在编写正确且强大的代码和过度工程之间有一条很好的路线。