I have a class A maintaining a list of objects class B.
But each object of class B can be referenced in any object of class A.
Class B also maintains a list of objects of class A where it is being referenced.
The program can and will create (several) objects of both class A and B ‘at will’ and also delete them.
If I use C# I can add and delete objects from both classes with following code
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;
}
}
This will work as because of removing/adding the object to the ListOfObjects the SECOND time (by recursion) the function will be called it will fail to delete/add thereby avoiding an infinite loop.
But I don’t like this code even though A and B do not know ‘much’ about the other class and just call a Delete/Add function.
I suppose this kind of problem is general and a design pattern exists for handling it in such a way that recursion can be avoided and updating both lists will be ‘just better’.
What design pattern should I use? I would appreciate if some code would be added as well.
You can simplify thing by moving the “object association concern” into a dedicated class. Here’s what I have in mind.
Define a class called AssociationTable. This class will maintain a list of pairs where each pair holds a reference to an A object and a reference to a B object.
Each A object (and each B object) will hold a reference to the AssociationTable object.
A.Add(B) will be implemented as table.add(this, b);
B.Add(A) will be implemented as table.add(a, this);
Deletion will be implemented as table.delete(this, b) or table.delete(a, this)
Edit:
The problem with this design is garbage collection. the table will hold references to objects thereby supressing their collection. In Java you could use a WeakReference object to overcome this issue. I am pretty sure there’s something similar in the .Net world
Also, the table could be a singleton. I don’t like singletons too much. In here, a singleton will make the A-B association unique across your program. This may be something that is undesirable but it depends on your concrete needs.
Finally, (just to put things in context) this design works the same way as Many-to-Many relationships in relational data bases.