保持对象图一致

时间:2009-02-01 08:32:51

标签: design-patterns oop

我有一种情况,其中对象A具有对对象B的引用.B也有对A的引用。为简单起见,假设A和B属于同一类型。当我更新A上的引用时,如何确保更新也将反映在B上(反之亦然)?

这种类型的接口示例:

interface IGraphNode
{
    IGraphNode From { get; set; }
    IGraphNode To { get; set; } 
}

执行下面的代码后,我希望B.From返回A.

IGraphNode A = new GraphNode();
IGraphNode B = new GraphNode();
A.To = B;

4 个答案:

答案 0 :(得分:1)

IGraphNode From
{ 
    get { return from; }
    set 
    {
        from = value;
        if (value.To != this) {
            value.To = this;
        }
    }
}

IGraphNode To
{
    get { return to; }
    set
    {
        to = value;
        if (value.From != this) {
            value.From = this;
        }
    }
}

您可能希望通过检查if(value == this)...

来扩展它

但是,如果您强制执行循环引用,则永远不能将IGraphNode用于非循环引用...

答案 1 :(得分:0)

您必须明确设置:

A.To = B;
B.From = A;

只要有可能,就是这样。大多数面向对象的语言透明地处理循环引用,例如这些。

如果您希望自动进行这种双向引用,您可以随时扩展IGraphNode接口并创建一个抽象基类,其中包含From和To属性中的一些代码,这些代码在修改时设置另一个值。需要此自动功能的所有GraphNode都应扩展基本抽象类。

答案 2 :(得分:0)

您需要拥有链接的A通知B,可能只需设置B.From属性。

但是,您需要考虑如果有多个对象获得B链接的内容:

IGraphNode A = new GraphNode();
IGraphNode B = new GraphNode();
IGraphNode C = new GraphNode();

A.To = B;
C.To = B;

// what should B.From return?

另外,想想如果其中一个引用的对象未被引用会发生什么?例如:

IGraphNode A = new GraphNode();
IGraphNode B = new GraphNode();

A.To = B;
A = null;  // should the reference from B keep the object 
           // that A used to reference alive?

WeakReference对象而不是直接引用可能有助于解决此特定问题。

答案 3 :(得分:0)

虽然接受的答案很聪明,但我并不喜欢它。特别是关于修改属性中的“值”的部分。 方法/属性不应该有隐藏的副作用。这样的做法通常会导致难以追踪的意外行为。期望在A上调用属性会修改我的B对象是不自然的。如果我明确检查代码,我只会知道这个吗?很多时候源代码甚至都不可用。

更好的解决方案是创建一个显式方法,使操作和任何副作用更明显,例如:

void ConnectNodes(IGraphNode a, IGraphNode b)
{
    a.to = b;
    b.from = a;
}

void ConnectNodes(IGraphNode b)
{
    this.to = b;
    b.from = this;
}
相关问题