E N D
Object Oriented Design We have spent a considerable amount of time in this course and in CPSC152 looking at the design of abstract data types. However, given a specific problem, we have not spent that much time considering how we design a solution to that problem using object oriented design. How do we determine what new data types should be designed? Object oriented design (OOD) begins with identifying key object types in the problem along with associated operations on those objects. What is an object?(loosely speaking) object Instance of fundamental data type Instance of a class
What is an operation on an object? operation global function member function built-in (++) How do we identify objects and operations? As a first-cut, we can use the narrative approach: the objects correspond to nouns in the problem description and the operations correspond to verbs. Having determined a list of nouns/objects we must then identify any redundancy in the list – sometimes we use different nouns to describe the same object. We must then determine which objects play a “significant” role in the problem. There is no cookbook formula for doing this. Let’s consider an example…
Alley A Alley B Example: (ref: “Data Abstraction in C++”, Headington & Riley) Write a program using OOD to simulate a parking lot.This particular lot consists of two alleys, each of which is wide enough for only one car and is closed at one end. Alley A is the primary parking location. Alley B is used only as a place to move cars in order to retrieve a car from the middle of Alley A. Program execution starts with both alleys empty. The program repeatedly prompts the user to specify one of four commands: either park a car, retrieve a car, print the contents of alley A or terminate the program. To park a car, the program generates a new ticket number (1, 2, 3…) and issues a stub to the customer.
To retrieve a car, the program prompts for a ticket number and reads it from the user. Each car at the front of alley A is then moved into alley B until the desired car is found. All of the cars that were temporarily moved into alley B are then returned to alley A. Identify the objects and operations: we will apply the noun-verb analysis of the problem description to come up with a first-cut at the objects and associated operations:
We will now summarize the objects and their associated operations in an object table: ObjectCharacteristics Operations
This table can be refined by deleting any objects that are redundant. Notice that the car object doesn’t have any characteristics that appear to be significant to our simulation. In fact, our program tracks cars by the associated ticket number. Parking a car is equivalent to inserting a ticket number into the alley. We can therefore go back to our object table and strike the car object. Having identified the significant objects, we must now establish the relationship between these objects. When we think of the physical relationship of our objects in the real-world situation, we can claim that a pkgLot object has-a alleyA object, alleyB object and ticket object associated with it. We implement has-a relationships using containment – our pkgLot object will have an alleyA, alleyB and ticket object as private data members. The ticket object keeps track of the next ticket number.
We must now consider how to implement each of our objects and the associated operations. We have three possibilities: • use a fundamental data type • use an off-the-shelf ADT • create a new ADT • It is probably best to consider these in the order presented. If we can use a fundamental data type then this represents the simplest implementation. If we can use an off-the-shelf ADT then this saves us having to implement our own. We will resort to creating a new ADT only when the other two options fail.
The command object: The char data type will serve adequately in representing a command object: char command; The associated readCommand operation will be implemented as a global function: void readCommand( char& command )// Post: user has been prompted for single character// command and command has been read from keyboard// and converted to upper case{ }
The ticketStub object: The int data type will serve adequately in representing a ticketStub object: int ticketStub; The associated readTicket operation will be implemented as a global function: void readTicket( int& ticketStub )// Post: user has been prompted for ticket number// and number has been read from keyboard{ }
The ticket object: The int data type will serve adequately in representing a ticket object: int ticket; The associated InitTicketToZero operation and GenNewNumber operations can be implemented using built-in C++ operations: ticket = 0; ticket++; The alleyA and alleyB objects: Both of these objects store ticket numbers (representing cars) in ______ order. The only ticket number that is accessible is the one at the front of the alley. It is therefore natural to represent these objects using an off-the-shelf ADT:
The pkgLot object: This object has three sub-objects: alleyA, alleyB and a ticket. There is certainly no fundamental data type that represents such an object, neither are we likely to find an off-the-shelf ADT with such attributes! We must therefore design our own ADT. class CPkgLot{public: CPkgLot(); void Park( void ); void Retrieve( int ticketStub ); void Display( void );private: ______________ alleyA; ______________ alleyB; ______ ticket;};
The next step is to implement the member functions of this class – we will not do that here. Having chosen a representation for each of our objects and implemented each of the associated operations, we now implement our program – a fairly straightforward matter given that most of the key operations are already implemented.