10.8.3. Multiple Association

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

Previously, we explored multiplicity in the context of whole-part relationships but focused on aggregation. We 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. Multiple associations build on and extend these ideas by allowing multiplicity (i.e., multiple pointers) at both ends of the relationship. 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 data and operations discovered during analysis. Using the contractor and project classes, we illustrate how the problem can sometimes help make this decision. We begin by imagining that the problem requires us to know the contractor's pay rate and the time worked on the project and to calculate the contractor's pay. But which class should be responsible for providing these features?

Scenario 1 (Figure 1(a))
Recently, a contractor undertook a project to add a ventilation fan to my garage. He set his pay rate and monitored his time. In this case, the contractor class manages the data and operations.
Scenario 2 (Figure 1(a))
Before teaching full-time, I worked for a company that often used contractors. Each project had a unique cost code and pay rate and tracked engineers' and contractors' times the same. In this case, the project manages the features.
Scenario 3 (Figure 1(b))
This scenario assumes that a contractor is not operating under an exclusive contract and may work on multiple projects simultaneously. The pay rate and time allocated to each project vary, making the contractor responsible for these features.
Scenario 4 (Figure 1(c))
In this scenario a project has many contractors. If the contractors have various skill levels or tasks and work varying amounts of time, the project must assume responsibility for the features.
Scenario 5 (Figure 1(d))
Finally, we imagine that many contractors work on many projects. Companies often temporarily supplement their engineering staff with contractors to complete time-sensitive projects. In this case, the conditions and solutions outlined in scenario 3 are appropriate. However, companies sometimes hire contractors as consulting engineers or subject matter experts (SMEs) when specialized skills are needed. These contractors set their rate and manage their own time, which is best described by scenario 4.

Scenario 5 presents a challenge that only considering responsibilities fails to resolve. In this scenario, the pay rate, time, and function to calculate the contractor's pay is not the responsibility of either class - it is the responsibility of the association relationship itself! But we implement association with pointers, which do not support data or functions. So, how do we overcome this imitation?

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.