Скачиваний:
64
Добавлен:
15.03.2015
Размер:
4.31 Mб
Скачать

Chapter 5 • YOUR FIRST OBJECT-ORIENTED C# PROGRAM 133

Note

The programmer who implements the Elevator class makes use of the NewFloorRequest method of a Person object. However, he or she should not need to look at the method definition to use the method. He or she would most likely not be interested in how a Person object decides on the values returned and would happily be unaware of random number generators and the like. The method header and a short description of the intent of the method is all that he or she needs to know. Information of how the intent is accomplished has no place here.

The method header forms a contract with the user of the method. It gives the name of the method and how many arguments should be sent along with the method call. The method then promises to return either no value (if stated void) or one value of a specific type.

So as long as we don’t tinker with the method header (don’t change the name of the method, the number and type of its formal parameters, or its return type), we can create all sorts of intricate processes for the Person object to decide on the next destination floor.

The Main() Method: Conducting the Simulation

In lines 53–63, we find our old friend the unavoidable Main method.

53:public static void Main()

54:{

55:elevatorA = new Elevator();

56:elevatorA.LoadPassenger();

57:elevatorA.InitiateNewFloorRequest();

58:elevatorA.InitiateNewFloorRequest();

59:elevatorA.InitiateNewFloorRequest();

60:elevatorA.InitiateNewFloorRequest();

61:elevatorA.InitiateNewFloorRequest();

62:elevatorA.ReportStatistic();

63:}

Even if Main() is positioned at the end of the program in this case, it contains, as always, the statements that are to be executed first when the program is started. You can view Main() to be a “control tower” of the whole program. It uses the overall functionality provided by the other classes in the program to direct the general flow of execution.

Briefly, the Main method initially creates an Elevator object and assigns it to elevatorA (line 55); instructs it to load in a passenger (line 56); asks elevatorA to request a “next floor request” along with its fulfillment five times (lines 57–61); and finally, it asks the Elevator object to report the statistic it has collected over those five trips (line 62).

Note how relatively easy it is to conduct this simulation from the Main method. All the hard detailed work is performed in the Elevator and Person classes.

Class Relationships and UML

The three user-defined classes, along with the System.Random class of Listing 5.1, collaborate to provide the functionality of our simple elevator simulation program. The Building class contains an Elevator object and calls its methods, the Elevator object employs a Person object to direct its movements, and the Person object uses a System.Random object to decide

134 C# PRIMER PLUS

the next floor. In well-constructed, object-oriented programs, classes collaborate in similar ways—each contributing with its own unique functionality—for the whole program to work.

If two classes are to collaborate, they must have a relationship (interact) with each other. Several different relationships can exist between two classes, and it is up to the designer of the program to decide which particular relationships should be implemented for the program at hand. This design phase typically takes place when the classes of the program have been identified (stage 2b of the design process described in Chapter 2, “Your First C# Program”). The following section discusses a few commonly found relationships.

Building-Elevator and Elevator-Person form two kinds of relationships that we will use as examples.

The Building-Elevator Relationship

A typical building is composed of many different parts, such as floors, walls, ceilings, a roof, and sometimes elevators. In our case, we can say that the Building we are simulating has an Elevator as one of its parts. This is sometimes referred to as a whole/part relationship. We have implemented this relationship in Listing 5.1 by declaring an instance variable of type Elevator inside the Building class as in line 51:

51:private static Elevator elevatorA;

This allows Building to hold an Elevator object and call its public methods. A class can have many different instance variables holding many objects of different classes. For example, we could also have equipped Building with instance variables representing a number of Floor objects. This concept of constructing a class (Building) with other classes (Elevator or Floors or both and many others) is generally called aggregation, and the accompanying relationships aggregation relationships.

If the aggregation relationship (as in the case of the Building-Elevator relationship), is reflecting a situation where one class is an integral part of the other, we can further call this aggregation a composition. (In a moment you will see why the Elevator-Person relationship is an aggregation but not a composition). The composition relationship can be illustrated with a Unified Modeling Language (UML) class diagram as shown in Figure 5.3. The two rectangular boxes symbolize classes and the line connecting them with the black diamond (pointing at the whole class) illustrates a composition relationship between the classes. Both classes are marked with the number 1 to indicate that one Building has one Elevator.

The Unified Modeling Language (UML): The Lingua Franca of OO Modeling

Pseudocode is a useful aid in expressing algorithms that are implemented in single methods because they are read from top to bottom, like the runtime executes the program, and because it abstracts away from the hard-coded rigor of a computer language (semicolons, parentheses, and so on). However, classes can consist of many methods, and larger programs consist of many classes. Pseudocode is not a suitable tool to illustrate models of how the classes of a program relate, because classes break free of the sequential procedural-oriented way of thinking (every class can potentially have a relationship with any other class defined in the program) and because the format of the pseudocode is much too detailed to provide an overview of a large OO program.

Chapter 5 • YOUR FIRST OBJECT-ORIENTED C# PROGRAM 135

To model class relationships and the overall architecture of an OO program effectively, we need a language that allows us to abstract away from the internal details of methods and, instead, provide us with the means to express class relationships and OO concepts on a suitable level of detail. For this purpose, most OO programmers today, irrespective of their programming language, use a graphical diagramming language called the Unified Modeling Language (UML). UML is a feature-rich language and requires a whole book to be amply presented; accordingly, this book only presents a small subset of UML.

You can get detailed information about UML from the non-profit organization Object Management Group (OMG) (www.omg.org) at www.omg.org/uml. Many good UML books have been written including The Unified Modeling Language User Guide by the originators of UML, Grady Booch, James Rumbaugh, and Ivar Jacobson.

FIGURE 5.3

Building

whole

UML diagram symboliz-

1

 

ing composition.

 

 

 

composition

1

Elevator

part

The Elevator-Person Relationship

A button is an integral part of an elevator, but a passenger is not. (The elevator is still fully operational without a passenger, but not without its buttons). So even though the passenger in our implementation (for abstraction reasons) has been made a permanent part of the Elevator (the same Person object stays inside the Elevator throughout the simulation), it is not a composition relationship, merely an aggregation. The relationship is illustrated with UML in Figure 5.4. Notice that an open diamond, in contrast to the filled diamond in Figure 5.3, symbolizes aggregation.

FIGURE 5.4

Elevator

UML diagram symboliz-

1

ing aggregation.

aggregation

 

 

1

 

Person

The whole UML class diagram for the program in Listing 5.1 is shown in Figure 5.5. UML allows us, as shown, to divide the rectangle representing a class into three compartments—the upper compartment contains the name of the class, the middle compartment the instance variables (or attributes), and the lower compartment the methods (behavior) belonging to the class.

136 C# PRIMER PLUS

FIGURE 5.5

 

Building

 

 

 

UML class diagram for

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Listing 5.1.

 

 

 

 

 

 

 

Main()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Elevator

 

 

 

 

 

 

 

 

 

 

 

currentFloor

 

 

 

 

requestedFloor

 

 

 

 

totalFloorsTraveled

 

 

 

 

 

 

 

 

 

 

 

LoadPassenger()

 

 

 

 

InitiateNewFloorRequest()

 

 

 

 

ReportStatistic()

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Person

 

1

1

System.Random

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

NewFloorRequest()

 

 

 

Next()

 

 

 

 

 

 

 

 

Associations

Permanent relationships between classes, such as the aggregation and composition relationships discussed in the previous sections, are generally called structural relationships or, more formally, associations. However, other types of associations exist that are not aggregations (and therefore not compositions either). To give an example of the latter, consider the following scenario: In an attempt to make our elevator simulation more realistic, we change our original list of abstractions shown earlier by allowing many Person objects to enter, travel, and exit the Elevator object instead of just the one Person object that permanently stays there at the moment. Any one Person object could then no longer be said to be a permanent part of the Elevator object, and we would just say that the Elevator class is associated with the Person class. An association is shown with a simple line as in Figure 5.6.

FIGURE 5.6

Elevator

Elevator/Person class

currentFloor

association.

requestedFloor

 

 

totalFloorsTraveled

 

LoadPassenger()

 

InitiateNewFloorRequest()

 

ReportStatistic()

 

1

 

1

 

Person

NewFloorRequest()