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.