双向关联,哪个更好?

Bidirectional association, what's better?

问题不大,但是我想过很多次如何在代码中实现双重关联...

让我们举个例子。一个男人车戴一个帽子,一个帽子可以戴在一个男人身上。但如果是男人戴帽子,那帽子的主人就一定是那个男人。

这是我以前的做法 (Java) :

字符中:

public void setHat (Hat hat) {
    Hat former = this.hat;
    this.hat = hat;
    if (former != null && former.getOwner() == this)
        former.setOwner(null);
    if (hat != null && hat.getOwner() != this)
        hat.setOwner (this);
}

帽子中:

public void setOwner (Character c) {
    Character former = this.owner;
    this.owner = c;
    if (former != null && former.getHat() == this)
        former.setHat(null);
    if (c != null && c.getHat() != this)
        c.setHat (this);
}

这样一来,男人的帽子和帽子的主人总是很协调。

但是...这对我来说听起来有点笨拙。请问实现这种条件 setter 的更好方法是什么?对我很有用。

(如果我说错了,那只是因为长棍面包好吗?^^)

UP,请^^

一些设计原则适用。 封装 意味着您不会让任何一个对象(帽子或人)处于不一致的状态。我认为您正在通过您的解决方案实现这一目标。

第二个原则称为 Demeter 法则,它的存在是为了通过减少耦合来简化软件维护。它声明一个方法应该只使用

  • 其class
  • 的实例字段
  • 参数
  • 它用new
  • 构造的对象

目的是让该方法避免要求另一个对象给它一部分内部状态来处理。由于 Hat 有一个 Man 类型的实例字段,反之亦然,它可能还不错。

一个可以应用的设计模式(如果你想去掉冗余代码)可能是 Mediator。这是解决方案的一部分(您实际上可以只使用 class 来处理管理,而不必一直使用中介模式):

这样做的缺点是 Man.setHatHat.setMan 是 public 方法,任何人都可以在不遵守您可以编程的 "global" 条件的情况下调用你的调解员来做。例如,其他一些 class 可以在几个不同的 Man 对象上调用 setHat(h)

在这种情况下,您可以使用断言(按合同设计)来确保调用这些方法的任何人都不会违反所谓的不变量,例如,Man.setHat(h) 的先决条件是 h.man == null OR h.man == this(它还没有被另一个男人穿)。但是,我不确定这样做是否比您当前的代码 笨拙 少。

最后,您可以在不使用双向关联的情况下应用 KISS 原则。例如,如果 Hat 必须知道它在哪个 Man 上(可能不太可能发生),那么您可以实现一个 Hat.getMan() 方法来遍历已知 Man 列表] 对象,搜索自身(如果您担心凝聚力,则使用其他 class 为您找到它)。性能是您可能不想这样做的原因。

相关问题:https://softwareengineering.stackexchange.com/questions/200949/class-design-with-bi-directional-relationships