Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 保持对象图的一致性_Design Patterns_Oop - Fatal编程技术网

Design patterns 保持对象图的一致性

Design patterns 保持对象图的一致性,design-patterns,oop,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(); IGraphN

我有一种情况,一个对象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;

必须明确设置:

A.To = B;
B.From = A;
只要有可能,就是这样。大多数面向对象语言都透明地处理这样的循环引用

如果您希望使这种双向引用自动化,那么可以扩展IGraphNode接口并生成一个抽象基类,该基类在From和to属性中包含一些代码,这些代码在修改时设置其他属性的值。所有需要此自动功能的图形节点都应该扩展基本抽象类

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;
        }
    }
}
您可能希望通过检查(value==this)来扩展它


但是,如果强制使用循环引用,则永远不能将IGraphNode用于非循环对象

您需要有一个通知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对象而不是直接引用可能有助于解决此特定问题。

虽然公认的答案很聪明,但我不喜欢它。特别是关于修改属性内的“值”的部分方法/属性不应具有隐藏的副作用。这样的做法通常会导致难以追踪的意外行为。对a调用属性会修改我的B对象,这是不自然的。只有当我明确检查代码时,我才会知道这一点?很多时候,源代码甚至不可用

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

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


理想情况下,它应该是自动的-您将如何实现这一点?您的意思是“大多数面向对象的语言都不会透明地处理这样的循环引用”?我的意思是,像.NET这样的平台不会在A引用B和B引用A时阻塞。这类“有A”关系很常见,编译器都可以处理它们。您可以使用类似于
nodeA.Connect(nodeB)
的方法。它将更加对称,您可以使用
.To
.From
来表示非循环的内容。为什么要使用支票?为什么不只是“value.From=this;”?
void ConnectNodes(IGraphNode b)
{
    this.to = b;
    b.from = this;
}