Design Patterns – Managing Deep Many-to-Many Relationships

data structuresdatabase-designdesign-patternsobject-oriented-design

I'm having trouble defining this data pattern I've come across working on several applications.

It consists of:

  1. An object type which is composed of many objects itself
  2. A second object type, where each instance 'has many' of the first object
  3. And, each of the sub-objects of the first object are modifiable per each association to the second object type.

A simple example might be:

  1. A programming course consisting of a set of lessons
  2. The lessons are composed of a set assignments.
  3. A course can be assigned to a student.
  4. However, once a course is assigned to a student each lesson and/or assignment can be customized to that student, with removals and additions, to the point where the original course may be unrecognizable.

In my solutions, what this results in is:

On assignment of a course to a student, the course is loaded into memory. Then for each sub-object, a student/sub-object relationship object is generated with the appropriate metadata. Essentially, I'm using the original object as a template to generate the required customizable objects.

This results in a huge amount of data as the sub-objects become more complex and numbered. I'm wondering if there is some optimization or pattern to reduce the amount of logic/complexity required to manipulate this data pattern.

Best Answer

I see a few options depending on what you need: (1) if there are many unique instances that follow a common algorithm, (2) if there are many similar objects or you will generated objects at run-time, and (3) if you want to dynamically modify the object's behavior while running. Note: you can combine all of the patterns I mention here, if need be.

  1. If each "second object type" is unique but follows a similar pattern of behavior, you could use Template Pattern. It sounds like you may be doing this. But to make it explicit, your abstract, base class has general algorithm programmed; certain steps of this algorithm are implemented in the derived classes.

  2. If you will create many objects or if creating objects at run-time is important to you, you could use Factory Pattern.

  3. And if you wish to dynamically change behavior, Stategy Pattern could work. For example, if a student in a regular curriculum is decided to be special needs or to go into an accelerated program. This works by composing the "student" of an object that would represent a base-class of the curriculum. The curriculum would be assigned to a derived curriculum at the student's construction (that sounds weird) and could be reassigned to another derived curriculum later.

(Just FYI, if using (3) Strategy Pattern with C++, you will have to Rvalues for composition.)

To store your objects and second objects, it may be worth considering Iterator Pattern (to cycle through them, add, delete, sort, etc.).

A good reference is Head First Design Patterns, which covers the patterns I mention and their implementation. They work in Java.

Related Topic