Previous Section  < Free Open Study >  Next Section

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');

}

    Previous Section  < Free Open Study >  Next Section