2

想象一下这些关系:

  • 1 A 有很多 B
  • 1B有很多C...

相反:

  • C有1个B
  • B有1A
  • 通过传递性,C 有 1 A

为了在 DB 中建模这种关系,我们有:

TableA
a_id

TableB
b_id
a_id (fk to TableA)

TableC
c_id
b_id (fk to TableB)

为了在 OO 中建模这种关系,我们有:

objA
objB
objC

并且... - objB 引用了 objA - objC 引用了 objB

如果objC有一个方法需要调用objA的一个方法,你会怎么做?

选项1。

b.getA().runMethodX()

我知道很多人会这样做,但我也知道这不好,因为 getA() 不是纯面向对象意义上的 B 行为。这样做就像进行过程编程一样。同意不同意?

选项 2。

让objC通过构造函数注入/setter直接引用objA和objB

这是一个好主意吗?但随后 objC 引用的 objB 也引用了 objA。这个可以吗?或者只要不是循环对象引用的情况,就可以接受?

选项 3。

将有问题的方法移动到objA,并通过参数传入objC。

我不确定这是否是一种选择。我认为它不会在所有情况下都有效。让 objC 中的方法减少到仅适用于其状态的最低限度,并让 objA 做 objA 之前或之后需要做的任何事情。

选项 4. (代表团)

将 runMethodXinA() 添加到 B,它调用

a.runMethodX()

C 调用

b.runMethodXinA()

我之前尝试过这种方法,但是 B 很可能最终会拥有与 A 一样多的方法,并且 B 和 A 中没有 1 个方法违反 DRY?

你的虽然是什么?还有其他选择吗?评论?建议?

4

5 回答 5

2

选项 2 是一种相当危险的信息重复,此外,根据您的环境,参考图的形状可能会出现任何问题。

如果方法在某种意义上依赖于 objA 的类型,选项 3 可能有意义,作为一种双重调度。

选项 1 违反了得墨忒耳法则,但听起来它是最不具侵入性的选项。

您可能还需要考虑 objB 上的转发方法,该方法将调用传递给 objA。

于 2009-02-19T03:42:14.053 回答
0

从您的选择列表中,选择是选项 4,因为它遵守得墨忒耳法则

  • 选项 1 违反得墨忒耳定律
  • 选项 2 引入了冗余引用间接违反了得墨忒耳定律
  • 选项 3 用对象 C 的知识污染对象 A,这也可以说违反了得墨忒耳定律(相反)

剩下选项4

可能有一个选项 5,但这超出了原始问题的范围;-)

于 2009-02-19T02:48:51.793 回答
0

我认为问题是你想要什么样的模型。如果您要使用一个关系模型,您可以提前知道整个结构并且它不会改变,那么选项 1 是可以接受的。也就是说,C 需要特定组织模式中 A 中的数据/方法。

选项 2 似乎是个好主意。但是您实际上是在保存对同一对象的两个引用。现在,如果 B 被映射到不同的 A,B 也必须通知 C 更改其引用。不好。

然而,选项 4 似乎是采用真正 OO 方法的正确方法。关键是A可以改变它的结构,你只需要适应B——直接的孩子。C 不知道也不关心 A 是如何实现的,只要 A 存在并且 B 知道如何处理它就足够了。

于 2009-02-19T02:50:48.530 回答
0

你真的需要从 C 到 B 到 A 的反向指针,还是只有它们才能从 C 访问 A?也许 A 应该负责创建 B 和 C 并管理他们的关系。在这种情况下,A 可以在创建 C 时将自己插入到 C 中(例如,C 可能有一个接受 A 的构造函数)。

您还可以在 A 上隔离 C 需要的函数并为其创建接口。接口(而不是 A)将在构造时传递给 C。这将使 C 与 A 分离。

于 2009-02-19T03:24:47.620 回答
0

1号或4号视情况而定。在我的金属切削软件中,我们有很多需要知道对象的父/源的实例。例如,我们在配件上有一个路径集合,每个路径都有一个配件属性,该属性返回创建它的配件。

但是,如果一个连接的对象只是因为它帮助原始对象实现其目的(如数学支持)而存在,那么委派可能是更好的方法。

如果连接的对象修改了原始对象,那么您最好使用访问者模式。

唯一需要注意的是,在大多数 OOP 中,您必须小心双重链接对象。对于具有相互连接的父子链接的对象,垃圾收集通常会失败。忘记清理父子链接是一个常见的错误。

使用支持创建和使用事件的 OOP,您可以解决此问题。通过使用代理。父母将交给孩子一个代理对象而不是自己。当孩子需要父母时,它将从代理对象获得引用。代理对象反过来作为一个事件引发,导致父对象返回自身。没有硬链接,因此减轻了程序员或垃圾收集器不清理的问题。

于 2009-02-19T13:14:21.697 回答