不是真的有问题,但我多次想知道如何在代码中实现双重关联......
我们有一个例子。一辆男子汽车戴着一顶帽子,帽子可以戴在一个男士身上。但如果男人戴帽子,帽子的主人必须是那个男人。
以下是我以前的做法(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);
}
在 Hat :
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);
}
这样,男人的帽子和帽子的主人总是协调一致。
但是......这对我来说听起来有点笨拙。请问有什么更好的方法来实现这种条件设置器?这对我非常有用。
(如果我犯了错误,那只是因为长棍面包好吗?^^)
UP,请^^
答案 0 :(得分:1)
一些设计原则适用。 封装意味着你不会让你的任何一个对象(帽子或人)处于不一致的状态。我认为你的解决方案正在实现这一目标。
第二个原则被称为Demeter 的法则,其存在是为了通过减少耦合来使维护软件更容易。它声明一个方法应该只使用
new
目的是让方法避免让另一个对象给它一部分内部状态来处理。由于Hat有一个Man类型的实例字段,反之亦然,它可能不是那么糟糕。
可以应用的设计模式(如果您想要删除冗余代码)可能是Mediator。这是解决方案的一部分(你可以真正使用一个处理管理的类,而不是一直使用Mediator模式):
这方面的缺点是Man.setHat
和Hat.setMan
是公共方法,可以被任何人调用,而不必考虑您可以为Mediator编程的“全局”条件。例如,其他一些类可以在几个不同的setHat(h)
对象上调用Man
。
在这种情况下,你可以使用断言(按合同设计)来确保任何调用这些方法的人都不会违反所谓的不变量,例如,Man.setHat(h)
的前提条件是h.man == null OR h.man == this
(它还没有被另一个人穿着)。但是,我不确定是否会比当前代码做的更少笨拙。
最后,您可以在不使用双向关联的情况下应用 KISS 原则。例如,如果Hat
必须知道它所在的Man
(可能不太可能发生),那么您实现了一个Hat.getMan()
方法,该方法遍历已知{{1}列表}对象,搜索自己(或者如果你担心凝聚力,可以使用其他类来为你找到它)。性能是您可能不想这样做的原因。