10.8.3. Multiple Association

Time: 00:05:36 | Download: Large, Large (CC), Small | Streaming (CC) | Slides (PDF)
Review

Multiple association is the confluence of multiplicity and viewing association as bidirectional aggregation, representing the most general and expressive constructive class relationship. However, this flexibility has a price: it's also the most challenging to understand and program. Programmers implement simple (one whole and one part) aggregation with a pointer in the whole class and more complex aggregation (one whole and many parts) with multiple pointers. We can organize the multiple pointers as an array or an instance of a container class (e.g., a vector). Similarly, multiple associations allow both peers to associate with one or many instances of the opposite peer; programmers implement multiple associations with multiple pointers. The following figure illustrates the multiplicity syntax describing four possible organizations.

Two classes, contractor and project, connected by association. The association connector is labeled with '1' at both ends. The association connector is labeled with '1' near the contractor  and '0..*' near the project class.
(a)(b)
The association connector is labeled with '1..*' near the contractor class and '1' near the project class. The association connector is labeled with '0..*' at both ends.
(c)(d)
Association with multiplicity operators. Four versions of an association relationship between a project and a contractor.
  1. One-to-one: A contractor has one project and a project has one contractor.
  2. One-to-many: A contractor has many projects, but a project only has one contractor.
  3. One-to-many: A contractor has one project and a project has many contractors.
  4. Many-to-many: Many contractors have many projects and many projects have many contractors.
The label "many-to-one" is equivalent to "one-to-many." The default multiplicity value is 1, making the label "1" optional.

Association generally and multiplicity specifically challenge class developers when choosing which class to make responsible for managing the program's necessary data and operations. A few scenarios illustrate how the original problems help guide the selection. The scenarios build on the contractor and project classes illustrating association throughout the text. The examples begin by assuming that each problem requires the program to manage the contractor's pay rate and time worked and calculate the contractor's pay. The class designer's task is to determine which class is responsible for providing these features.

Scenario Description UML
1 A homeowner hires a contractor to do a small home repare project. The contractor has a single client with a single project, and the client has a single contractor. The contractor sets the pay rate and monitors the time. In this case, the contractor class manages the data and operations. rate, time, and calc_pay are contractor features.
2 Alternatively, the client may advertise the project and its pay rate. Furthermore, the client may track the contractor's working time. In this case, the project manages the features. rate, time, and calc_pay are project features.
3 A homeowner hires a contractor to build a deck, a project requiring time for the concrete to set. A busy contractor has many ongoing projects to fill the waiting time. The pay rate and time allocated to each project vary, so the contractor is responsible for these features. The contractor has many projects, and the rate, time, and calc_pay are contractor features.
4 I worked as a software engineer for a company that often used contractors. The contractors worked on various projects, were paid differently, and worked different amounts of time. In this case, the project manages the features. The project has many contractors, and the rate, time, and calc_pay are project features.
5 Imagine many contractors working simultaneously on many projects. For example, companies sometimes hire contractors as consulting engineers or subject matter experts (SMEs) when specialized skills are needed. These contractors frequently divide their time between projects, so they negotiate project rates and bill for time worked. The features controlling the contractor's pay do not "belong" to either class - they belong to the specific association between a contractor and a project.
Locating class responsibilities. Identifying the class responsible for specific features in one-to-one and many-to-one association relationships is relatively easy. However, many-to-many association relationships often present a challenge that considering responsibilities alone fails to resolve. In this scenario, the features are not the responsibility of either class - they are the responsibility of the association relationship itself! However, C++ implements associations as pointers, which do not support data or functions. Class designers solve this problem with link classes.

When we instantiate classes connected by aggregation or association, we simultaneously instantiate the connections between the objects. The UML calls these connections links. When a class design assigns responsibilities to the associations in a many-to-many relationship, we can manage the data and functions with a construct called a link class.