我有一个A类,维护一个B类对象列表。 但是B类的每个对象都可以在A类的任何对象中引用。 B类还维护一个A类对象的列表,它被引用。 该程序可以并将随意创建(几个)A类和B类的对象,并删除它们。
如果我使用C#,我可以使用以下代码添加和删除这两个类中的对象
public class A
{
private List<B>ListOfObjects_B;
public bool Add(B Object)
{
bool bAdd = false;
if ((Object != null) && (ListOfObjects_B.IndexOf(B) <0))
{
ListOfObjects_B.Add(Object);
Object.Add(this);
bAdded = true;
}
return bAdded;
}
public bool Delete(B Object)
{
bool bDeleted = ListOfObjects_B.Remove(Object);
if (bDeleted == true) Object.Delete(this);
return bDeleted;
}
}
public class B
{
private List<A>ListOfObjects_A;
public bool Add(A Object)
{
bool bAdd = false;
if ((Object != null) && (ListOfObjects_A.IndexOf(A) <0))
{
ListOfObjects_A.Add(Object);
Object.Add(this);
bAdded = true;
}
return bAdded;
}
public bool Delete(A Object)
{
bool bDeleted = ListOfObjects_A.Remove(Object);
if (bDeleted == true) Object.Delete(this);
return bDeleted;
}
}
这将起作用,因为删除/添加对象到ListOfObjects SECOND时间(通过递归)函数将被调用它将无法删除/添加从而避免无限循环。
但我不喜欢这段代码,即使A和B不太了解其他类,只是调用删除/添加功能。
我认为这种问题是一般性的,并且存在一种设计模式,用于处理它,以便可以避免递归,并且更新两个列表将“更好”。 我应该使用什么设计模式?如果添加一些代码,我将不胜感激。
答案 0 :(得分:4)
您可以通过将“对象关联关注点”移动到专用类中来简化事物。这就是我的想法。
定义一个名为AssociationTable的类。该类将维护一对对列表,其中每对包含对A对象的引用和对B对象的引用。
每个A对象(以及每个B对象)将保存对AssociationTable对象的引用。 A.Add(B)将实现为table.add(this,b); B.Add(A)将实现为table.add(a,this);
删除将实现为table.delete(this,b)或table.delete(a,this)
class Pair {
A a; B b;
Pair(A a, B b) { this.a = a; this.b = b; }
// Also override Equals(), HashCode()
}
class AssociationTalbe {
Set<Pair> pairs = ...;
void add(A a, B b) { pairs.add(new Pair(a, b)); }
void remove(A a, B b) { pairs.remove(new Pair(a, b)); }
}
class A {
AssociationTable table;
public A(AssociationTable t) { table = t; }
void add(B b) { table.add(this, b); }
void remove(B b) { table.remove(this, b); }
}
编辑: 这种设计的问题是垃圾收集。该表将保存对象的引用,从而压制其集合。在Java中,您可以使用WeakReference对象来克服此问题。我很确定在.Net世界中有类似的东西
此外,该表可以是单身人士。我不太喜欢单身人士。在这里,单例将使A-B关联在您的程序中唯一。这可能是不受欢迎的,但这取决于您的具体需求。
最后,(只是为了把事情放在上下文中)这个设计与关系数据库中的多对多关系一样。
答案 1 :(得分:2)
我最近写了a class to handle a similar problem。它实际上是一个更简单的场景(父/子关系与孩子引用他们的父母),但你可能可以根据自己的需要调整它。主要区别在于我的实现中的Parent
属性应该由父项集合替换。
答案 2 :(得分:1)
关于我唯一能想到的是使用Mediator模式,以便A不会将自己添加到B.这是一个例子:
public class Mediator {
public void Add(A List, B Object) {
if(list.Add(Object)) {
object.Add(List);
}
}
public void Delete(A List, B Object) {
if(List.Delete(Object)) {
Object.Delete(List);
}
}
}
在此之后你将删除代码行“Object.Add(this);”和“if(bDeleted == true)Object.Delete(this);”这也有利于减少每个方法被调用的次数,因为对象A的方法被调用两次,因为对象B也在对象A上调用这些方法。
编辑:经过进一步审核,我意识到你已经在某种程度上使用了Observer设计模式。对象A是观察者,对象B是可观察对象。对象A维护其观察对象的列表,对象B维护观察它的对象列表。唯一的事情是我没有看到任何额外的功能,虽然可能有一些。基本上,对象B将通知所有对象A观察它已被更改,并且所有这些对象A将要求进行更改。如果这是您正在寻找的,那么您需要做的就是删除行“Object.Add(this);”和“if(bDeleted == true)Object.Delete(this);”来自B代码,因为它是不必要的。