Selected C++ Example #4 // Example #4 // This C++ example illustrates the better method for implementing // a fragment of the home heating system example described in // Booch's OOA/D book. This better solution pushes higher-level // functionality onto the Room class, making the heat flow // regulator less god-like. // This example illustrates several examples of containment. If // you are unfamiliar with the concept of containment, please read // Chapter 4 before working through this example. #include <iostream.h> #include <stdlib.h> #include <string.h> // Constants used in this example. const int name_len = 50; const int large_strlen = 128; const int room_len = 20; // These sensor classes are identical to those in the previous // example. See the comments on the classes in that example for // further information. class DesiredTempActuator { public: int get_temp(); }; // Returns a random number from 50 to 90 int DesiredTempActuator::get_temp() { return(random(41) + 50); } class ActualTempSensor { public: int get_temp(); }; int ActualTempSensor::get_temp() { return(random(41) + 50); } class OccupancySensor { public: int anyone_in_room(); }; // Returns a random value (0 or 1) int OccupancySensor::anyone_in_room() { return(random(2) % 2); } // The Room class contains a desired temperature input device, a // temperature sensor, and an occupancy sensor (all by value). It // has a name attribute for descriptive information. // Note that the accessor methods have been eliminated in favor of // a ''do_you_need_heat()'' method. class Room { char name[name_len]; DesiredTempActuator dtemp; ActualTempSensor atemp; OccupancySensor occ; public: Room(char*); int do_you_need_heat(); }; Room::Room(char* n) { strncpy(name, n, name_len); } // The Room object determines if it needs heat by calculating its // working temperature (desired - actual) and checking if anyone // is in the room. The room needs heat if the actual temperature // is less than the desired temperature and someone is in the room, // OR if no one is in the room and the actual temperature is more than // five degrees less than the desired temperature. // The method returns one if heat is needed and zero if not. int Room::do_you_need_heat() { int working_temp, occupied; working_temp = dtemp.get_temp() - atemp.get_temp(); occupied = occ.anyone_in_room(); cout << ''The'' << name << '' has a working temp of '' << working_temp; cout << '' and '' << (occupied ? ''someone in the room.\n'' : ''no one in the room.\n''); if (working_temp > 5 working_temp > 0 && occupied) { return(1); } return(0); } // Our furnace does little in this implementation of a design // fragment because it is relatively uninteresting to illustrate // the problem of poorly related data and behavior. class Furnace { public: void provide_heat(); void turnoff(); }; void Furnace::provide_heat() { cout << ''Furnace Running\n''; } void Furnace::turnoff() { cout << ''Furnace Turned Off\n''; } // The heat flow regulator does not contain a list of rooms and a // furnace. It is associated with them. There is a very large // difference between stating that a class contains an object by // reference, or a class is associated with an object. See // Chapter 7 for an indepth discussion on this subject. class HeatFlowRegulator { Room *house[room_len]; Furnace *heater; int room_num; public: HeatFlowRegulator(Furnace*, int, Room**); int loop(); }; // This constructor is identical to the one of the previous // example. HeatFlowRegulator::HeatFlowRegulator(Furnace* f, int num, Room **rooms) { int i; heater = f; room_num = num; for (i=0; i < room_num; i++) { house[i] = rooms[i]; } } // The looping of the heat flow regulator is to check each room to see // if it needs heat. In order to do this, the regulator simply asks // the room if it needs heat. The work of figuring out if heat is // needed has been pushed onto the Room class, which contains the // necessary information. int HeatFlowRegulator::loop() { int anyone_need_heat=0, i; for (i=0; i < room_num; i++) { anyone_need_heat += house[i]->do_you_need_heat(); } if (anyone_need_heat) heater->provide_heat(); else heater->turnoff(); return(anyone_need_heat); } void main() { int room_num, i, retval; Furnace our_furnace; Room *rooms[room_len]; char buffer[large_strlen]; cout << ''How many rooms in your house? ''; cin >> room_num; cin.get(); if (room_num > room_len) room_num = room_len; for (i=0; i < room_num; i++){ cout << ''What is the name of room['' << (i+1) << '']? ''; cin.getline(buffer, large_strlen, '\n'); rooms[i] = new Room(buffer); } HeatFlowRegulator h(&our_furnace, room_num, rooms); do{ retval = h.loop(); cout << retval << '' rooms required heat!\n''; cout << ''Continue? ''; cin.getline(buffer, large_strlen, '\n'); } while (buffer[0] == 'y'); } |