The Aircraft Engine Simulation: An Extended Aggregation Example

 < Day Day Up > 



It is time for a more complex example of compositional design. In this section you will study a software model of an aircraft jet engine. The name of the composite class is Engine and it contains several different part objects. Figure 12-5 shows the UML class diagram for the composite aggregate class Engine. As you can see from the diagram the diamonds are solid, indicating composite aggregation of each of the Engine’s part objects.

click to expand
Figure 12-5: Engine Composite Aggregation Class Diagram

The Purpose of the Engine Class

Any modeling effort requires a set of simplifying assumptions so I will define a few to apply here. First, and primarily, although the Engine class and its supporting classes represent a complex set of associations between several classes, it is by no means a literal model of an engine, so you will have to use some imagination. Its purpose is to suggest how the implementation of an aggregation comprised of more than one or two classes might look in source code. To this end all the objects respond to messages with simple text messages printed to the screen. What is important to take away from this example is how you think of complex class design which should be in terms of objects and their interfaces. Lastly, the number of parts comprising the Engine aggregate are kept at a manageable five. This will give you a taste for the potential physical complexity you might encounter on larger object-oriented design projects.

An Engine and its Parts

The Engine class is a composite aggregate object comprised of five user-defined abstract data types: FuelPump, OilPump, Compressor, TemperatureSensor, and OxygenSensor. An Engine’s behavior is derived from the behavior of these parts. Let us take a closer look at the behavior of one of these parts. Figure 12-6 shows the class diagram for the FuelPump class.

click to expand
Figure 12-6: FuelPump Class

The public interface functions, indicated by the leading + sign in the class diagram, define the behavior you can expect from a FuelPump object. The constructor takes two parameters: _status, which is of type PartStatus, and engine_number which is of type short. The short type is a fundamental C++ data type. The PartStatus type is an enumeration declared for the purpose of this example. The PartStatus declaration is located in a file named aircraftutils.h shown in example 12.13.

Listing 12.13: aircraftutils.h

start example
 1  #ifndef __AIRCRAFT_UTILITIES_H  2  #define __AIRCRAFT_UTILITIES_H  3  4  enum PartStatus {NotWorking, Working};  5  enum EngineStatus {NotReady, Ready};  6  7  #endif
end example

The PartStatus enum has two states: NotWorking and Working. When a FuelPump constructor is called the first argument must be of type PartStatus indicating whether the part is working or not. The second constructor parameter is the number of the engine to which the FuelPump object belongs.

The other public functions of FuelPump indicate the other behaviors FuelPump objects can exhibit. You can determine if a fuel pump is working properly by sending it an isWorkingProperly() message; you can set a fuel pump’s operational status by sending it a setStatus() message. You can register a fuel pump with a particular engine by sending it a registerWithEngineNumber() message, and lastly, you can determine to what engine number a fuel pump is registered to by sending it a getRegisteredEngineNumber() message. Essentially the public interface is a set of accessor and mutator functions that provide some rudimentary behavior.

All the other classes used in the Engine design have the same interface and therefore the same behavior. You may examine them more closely of you wish by studying figure 12-5.

The class declaration for the FuelPump class resides in a file named fuelpump.h and is shown in example 12.14.

Listing 12.14: fuelpump.h

start example
 1  #ifndef FUEL_PUMP_H  2  #define FUEL_PUMP_H  3  #include "aircraftutils.h"  4  5  class FuelPump {  6     public:  7        FuelPump(PartStatus _status = Working, short engine_number = 0);  8        ~FuelPump();  9        PartStatus isWorkingProperly(); 10        void setStatus(PartStatus _status); 11        void registerWithEngineNumber(short _engine_number); 12        short getRegisteredEngineNumber(); 13     private: 14        PartStatus status; 15        short registered_engine_number; 16  }; 17 18  #endif
end example

The Engine Class

The class diagram for the Engine class is shown in figure 12-7.

click to expand
Figure 12-7: Engine Class Diagram

It too presents a set of public interface functions which define the type of behavior you can expect from an Engine object. Besides creating and destroying an Engine object, you can check its status, start, stop, and set the status of each of its parts. Since the Engine class is a composite aggregate it controls the life of each of its parts.

The Engine class contains one static class-scope data member named engine_count. Class-scope data members appear underlined in UML class diagrams. There are two more data members to note: its_status is of type EngineStatus which is an enumerated type declared in the aircraftutils.h file; engine_is_running is a boolean variable which is used to indicate whether the engine is running or not.

Note that all the Engine class data members are private. The only authorized way to manipulate engine objects is through the Engine class’s public interface. Example 12.15 gives the source code for the Engine class declaration.

Listing 12.15: engine.h

start example
 1  #ifndef ENGINE_H  2  #define ENGINE_H  3  #include "aircraftutils.h"  4  #include "fuelpump.h"  5  #include "oxygensensor.h"  6  #include "oilpump.h"  7  #include "compressor.h"  8  #include "temperaturesensor.h"  9 10 11  class Engine{ 12    public: 13      Engine(); 14      ~Engine(); 15      EngineStatus checkEngineStatus(); 16      void startEngine(); 17      void stopEngine(); 18      void setFuelPumpStatus(PartStatus _status); 19      void setOilPumpStatus(PartStatus _status); 20      void setTemperatureSensorStatus(PartStatus _status); 21      void setOxygenSensorStatus(PartStatus _status); 22      void setCompressorStatus(PartStatus _status); 23 24    private: 25      static short         engine_count; 26      FuelPump             its_fuel_pump; 27      OilPump              its_oil_pump; 28      TemperatureSensor    its_temperature_sensor; 29      OxygenSensor         its_oxygen_sensor; 30      Compressor           its_compressor; 31      short                its_engine_number; 32      EngineStatus         its_status; 33      bool                 engine_is_running; 34  }; 35  #endif
end example

If you study the Engine class diagram in figure 12-7 you will find it matches closely what you see in the Engine class declaration above. A good UML design tool can do more than just draw pretty pictures; it can be used to flesh out the classes and their interfaces and to generate the framework code resulting from the design. Although the code shown above was not generated with a UML tool, it could easily have been.

Notice on lines 3 through 8 that all the required header files corresponding to each of the part classes are included.

Before we look at the Engine class implementation code let us take a look at the main() function and how Engine objects are created and used. Example 12.16 gives the source code for the main.cpp file used to run the aircraft engine program.

Listing 12.16: main.cpp

start example
 1  #include <iostream>  2  using namespace std;   3  4  #include "engine.h"  5  6  int main()  7  {  8     Engine e1,e2;  9 10     e1.checkEngineStatus(); 11     e2.checkEngineStatus(); 12 13     e1.stopEngine(); 14 15     e1.startEngine(); 16     e2.startEngine(); 17 18     e1.setCompressorStatus(NotWorking); 19     e1.checkEngineStatus(); 20 21     return 0; 22  }
end example

Two Engine objects are created on line 8, e1 and e2. Next, the checkEngineStatus() message is sent to each Engine object. On line 13 the stopEngine() message is sent to the e1 object. Since the engine has not yet been started this should result in a message saying something to that effect. Next, both engine objects are sent the startEngine() message.

On line 18, the e1 object is sent the setCompressorStatus() message with the NotWorking enumeration state value as an argument. This should result in the status of the compressor associated with Engine object e1 being set to NotWorking. The result of this message is tested by sending a checkEngineStatus() message to the e1 engine object. When the program terminates all engine objects and their associated part objects are destroyed. Figure 12-8 shows the results of running this program.

click to expand
Figure 12-8: Results of Running Example 12-16

Notice that the creation of each Engine object causes each part object to be created, as is indicated by the message each part object’s constructor prints to the screen. You can trace each message produced in figure 12-8 as a result of sending messages to each Engine object in the main() function.



 < Day Day Up > 



C++ for Artists. The Art, Philosophy, and Science of Object-Oriented Programming
C++ For Artists: The Art, Philosophy, And Science Of Object-Oriented Programming
ISBN: 1932504028
EAN: 2147483647
Year: 2003
Pages: 340
Authors: Rick Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net