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.
(a) | (b) |
(c) | (d) |
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. | |
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. | |
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. | |
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. | |
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. |
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.
class link; class contractor { private: link* projects[25]; }; |
class contractors; class project; class link { private: contractor* c; project* p; double rate; double time; public: calc_pay() : double; }; |
class link; class project { private: link* contractors[100]; }; |