What is the design template?

I have a class A that maintains a list of objects of 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 to which it refers. A program can and will create (several) objects of both class A and B 'as desired', as well as delete them.

If I use C #, I can add and remove objects from both classes with the 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, because due to deleting / adding an object to ListOfObjects in the SECOND time (by recursion) the function will be called, it will not be able to delete / add, thereby avoiding an infinite loop.

But I do not like this code, even if A and B do not know a lot about another class and simply call the Delete / Add function.

I assume that this problem is common and that there is a design pattern for handling it in such a way that recursion can be avoided and updating both lists would be β€œbetter”. What design model should I use? I would appreciate adding the code.

+4
source share
3 answers

You can simplify the task by moving the "association of objects" to the selected class. Here is what I mean.

Define a class called AssociationTable. This class will maintain a list of pairs, where each pair contains a link to an object A and a link to an object B.

Each object A (and each object B) will contain 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)

 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); } } 

Edit: The problem with this design is garbage collection. the table will contain references to objects, thereby suppressing their collection. In Java, you can use the WeakReference object to solve this problem. I'm sure there is something similar in the .Net world

In addition, the table can be single. I do not like singles too much. Here, a singleton will make the AB association unique in your program. This may not be desirable, but it depends on your specific needs.

Finally, (just to put things in context), this project works just like many-to-many relationships in relational databases.

+4
source

I recently wrote a class to handle a similar problem . This is actually a simpler scenario (parent / child relationship with children referring to the parent), but you could probably adapt it for your needs. The main difference is that the Parent property in my implementation should be replaced with a collection of parents.

+2
source

The only thing I can think of is using a mediation template, so A does not add itself to B. Here is an example:

 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); } } } 

After that, you will remove the lines of code that read "Object.Add (this);" and "if (bDeleted == true) Object.Delete (this);" It also reduces the number of times each method is called as an object before an object. Methods were called twice because object B also called these methods on object A.

EDIT: after further review, I realized that you already used the Observer design pattern. Object A is an observer, and object B is observable. Object A maintains a list of objects that it observes, and Object B maintains a list of objects that observe it. The only thing I do not see any additional features, although there are probably some. Basically, object B will notify the entire object A, observing that it has changed, and all objects of Object A will request a change. If this is what you are looking for, then all you have to do is delete the lines "Object.Add (this);" and "if (bDeleted == true) Object.Delete (this);" from code B, as this is optional.

+1
source

Source: https://habr.com/ru/post/1286454/


All Articles