Figure 4.6 shows the Booch diagram for the Component class and many of its related classes. The Component class itself is represented by the dotted cloud icon in the center of the diagram. The icon shows that this class has two data members (local_time and delay) and two member functions (simulate() and process()). The local_time data member contains the current local time of the class and the delay data member contains the transport delay of the component, which is initialized when the component is constructed. The simulate() and process() member functions are primarily responsible for the simulation aspects of the component; these details will be deferred until Section 4.3.5.
Figure 4.6: Component Class Diagram
Next, looking above the Component class, there are two adjacent classes named I_List and O_List. They are both associated with the Component class by a line with a filled circle at the Component end and a filled rectangle at the I_List/O_List ends. These two classes represent the list of input ports and output ports for the component. The filled circle symbolizes a containment or aggregation relationship. Because the input and output port lists are part of a component, this relationship is justified. The filled rectangle implies that the aggregation is a physical containment as opposed to a pointer/reference containment. By using physical containment, we are ensured that the lifetimes of the input and output port lists during the simulation will be the same as the lifetime of the enclosing component. The two small numbers adjacent to the end points of each of the lines signify the cardinality of the relationship. In other words, each component contains one input port list and one output port list.
Note that the I_List and O_List class icons each have a solid rectangle in their respective upper right regions. This adornment indicates that these two classes are actually instances of a parameterized class. The dotted lines with the arrow heads emanating from the I_List and O_List classes indicate that these two classes were instantiated from the List parameterized classes. This parameterized class provides rudimentary support for a generic linked list structure which can be manipulated in a type-safe manner. The text inside the solid rectangles of the I_List and O_List classes represent the actual arguments to the List parameterized class; the text inside the dotted rectangle of the List class represents the formal arguments. As with parameter passing in procedural languages, an association is established between the formal arguments and the actual arguments. In the context of this specific example, a correspondence between the Port * actual argument and the Type formal argument is created, thereby transforming I_List and O_List into list classes which contain pointers to Port objects. Note that in order for the instantiation to occur, the I_List and O_List classes both require the services of the Port class. This using relationship is shown by the solid line emanated from the Port class and ending with a hollow circle on the I_List/O_List classes.
Finally, we focus on the classes immediately below the Component class in the figure. These classes represent some of the lowest-level units of the component library, such as 2-input And and Or gates and a 1-input Not gate. They are related to the Component class by a solid line with an arrow pointing towards the Component class. This is an inheritance relationship -- an And gate is a kind of component, hence, we can derive And from Component. Note that each of the low-level gates contain their own process() method, thereby overriding the virtual process() member function in the base Component class.
The gates are also related to the Input and Output classes via several aggregation relationships, similar to the ones mentioned earlier. These relationships are used to illustrate the number of input and output ports contained within each component. For example, a 2-input Or gate contains two inputs and one output. Therefore, as the cardinality in the diagram shows, the Or gate physically contains two objects instantiated from the Input class and one object instantiated from the Output class.
On the surface, it may seem as though each component maintains two different sets of input ports and two different sets of output ports -- one such set is inherited from its base Component class, and another set is created from its aggregate data members when it is constructed. However, this is not true. Remember that the Component contains two lists which store pointers to Port objects and not Port objects themselves. The Port objects are actually created by classes derived from the Component class. As such, when a derived component is instantiated, its constructor will add pointers to its input/output ports to the corresponding port lists it inherits from the base Component class. In this way, the base Component class can have a generic mechanism which can traverse input and output ports, even though it doesn't know in advance how many such ports its derived components will have. This mechanism is then inherited by all of its derived classes instead of having to be duplicated in each one.