?? 018.htm
字號:
<P>It is possible that <TT>Condition</TT> objects are passed to the central <TT>Alarm</TT>
object, or that <TT>Condition</TT> objects are subclassed into <TT>Alarm</TT> objects,
which themselves know how to take emergency action. Perhaps there is no central object;
instead there might be sensors, which know how to create <TT>Condition</TT> objects.
Some <TT>Condition</TT> objects would know how to log themselves; others might know
how to contact the police.</P>
<P>A well-designed event-driven system need not have a central coordinator. One can
imagine the sensors all independently receiving and sending message objects to one
another, setting parameters, taking readings, and monitoring the house. When a fault
is detected, an <TT>Alarm</TT> object is created, which logs the problem (by sending
a message to the <TT>Log</TT> object) and takes the appropriate action.
<H4 ALIGN="CENTER"><A NAME="Heading10"></A><FONT COLOR="#000077">Event Loops</FONT></H4>
<P>To simulate such an event-driven system, your program needs to create an event
loop. An event loop is typically an infinite loop such as <TT>while(1)</TT>, which
gets messages from the operating system (mouse clicks, keyboard presses, and so on)
and dispatches them one by one, returning to the loop until an exit condition is
satisfied. Listing 18.1 shows a rudimentary event loop.</P>
<P><A NAME="Heading11"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 18.1. A simple
event loop.</B></FONT></P>
<PRE><FONT COLOR="#0066FF" font style="font-size:10pt">1: // Listing 18.1
2:
3: #include <iostream.h>
4:
5: class Condition
6: {
7: public:
8: Condition() { }
9: virtual ~Condition() {}
10: virtual void Log() = 0;
11: };
12:
13: class Normal : public Condition
14: {
15: public:
16: Normal() { Log(); }
17: virtual ~Normal() {}
18: virtual void Log() { cout << "Logging normal conditions...\n"; }
19: };
20:
21: class Error : public Condition
22: {
23: public:
24: Error() {Log();}
25: virtual ~Error() {}
26: virtual void Log() { cout << "Logging error!\n"; }
27: };
28:
29: class Alarm : public Condition
30: {
31: public:
32: Alarm ();
33: virtual ~Alarm() {}
34: virtual void Warn() { cout << "Warning!\n"; }
35: virtual void Log() { cout << "General Alarm log\n"; }
36: virtual void Call() = 0;
37:
38: };
39:
40: Alarm::Alarm()
41: {
42: Log();
43: Warn();
44: }
45: class FireAlarm : public Alarm
46: {
47: public:
48: FireAlarm(){Log();};
49: virtual ~FireAlarm() {}
50: virtual void Call() { cout<< "Calling Fire Dept.!\n"; }
51: virtual void Log() { cout << "Logging fire call.\n"; }
52: };
53:
54: int main()
55: {
56: int input;
57: int okay = 1;
58: Condition * pCondition;
59: while (okay)
60: {
61: cout << "(0)Quit (1)Normal (2)Fire: ";
62: cin >> input;
63: okay = input;
64: switch (input)
65: {
66: case 0: break;
67: case 1:
68: pCondition = new Normal;
69: delete pCondition;
70: break;
71: case 2:
72: pCondition = new FireAlarm;
73: delete pCondition;
74: break;
75: default:
76: pCondition = new Error;
77: delete pCondition;
78: okay = 0;
79: break;
80: }
81: }
82: return 0;
<TT>83: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: (0)Quit (1)Normal (2)Fire: 1
Logging normal conditions...
(0)Quit (1)Normal (2)Fire: 2
General Alarm log
Warning!
Logging fire call.
(0)Quit (1)Normal (2)Fire: 0
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The simple loop created on
lines 59-80 allows the user to enter input simulating a normal report from a sensor
and a report of a fire. Note that the effect of this report is to spawn a <TT>Condition</TT>
object whose constructor calls various member functions.<BR>
<BR>
Calling virtual member functions from a constructor can cause confusing results if
you are not mindful of the order of construction of objects. For example, when the
<TT>FireAlarm</TT> object is created on line 72, the order of construction is <TT>Condition</TT>,
<TT>Alarm</TT>, <TT>FireAlarm</TT>. The <TT>Alarm</TT> constructor calls <TT>Log</TT>,
but it is <TT>Alarm</TT>'s <TT>Log()</TT>, not <TT>FireAlarm</TT>'s, that is invoked,
despite <TT>Log()</TT> being declared virtual. This is because at the time <TT>Alarm</TT>'s
constructor runs, there is no <TT>FireAlarm</TT> object. Later, when <TT>FireAlarm</TT>
itself is constructed, its constructor calls <TT>Log()</TT> again, and this time
<TT>FireAlarm::Log()</TT> is called.
<H3 ALIGN="CENTER"><A NAME="Heading13"></A><FONT COLOR="#000077">PostMaster</FONT></H3>
<P>Here's another problem on which to practice your object-oriented analysis: You
have been hired by Acme Software, Inc., to start a new software project and to hire
a team of C++ programmers to implement your program. Jim Grandiose, vice-president
of new product development, is your new boss. He wants you to design and build PostMaster,
a utility to read electronic mail from various unrelated e-mail providers. The potential
customer is a businessperson who uses more than one e-mail product, for example Interchange,
CompuServe, Prodigy, America Online, Delphi, Internet Mail, Lotus Notes, AppleMail,
cc:Mail, and so forth.</P>
<P>The customer will be able to "teach" PostMaster how to dial up or otherwise
connect to each of the e-mail providers, and PostMaster will get the mail and then
present it in a uniform manner, allowing the customer to organize the mail, reply,
forward letters among services, and so forth.</P>
<P>PostMasterProfessional, to be developed as version 2 of PostMaster, is already
anticipated. It will add an Administrative Assistant mode, which will allow the user
to designate another person to read some or all of the mail, to handle routine correspondence,
and so forth. There is also speculation in the marketing department that an artificial
intelligence component might add the capability for PostMaster to pre-sort and prioritize
the mail based on subject and content 888 and associations.</P>
<P>Other enhancements have been talked about, including the ability to handle not
only mail but discussion groups such as Interchange discussions, CompuServe forums,
Internet newsgroups, and so forth. It is obvious that Acme has great hopes for PostMaster,
and you are under severe time constraints to bring it to market, though you seem
to have a nearly unlimited budget.
<H3 ALIGN="CENTER"><A NAME="Heading14"></A><FONT COLOR="#000077">Measure Twice, Cut
Once</FONT></H3>
<P>You set up your office and order your equipment, and then your first order of
business is to get a good specification for the product. After examining the market,
you decide to recommend that development be focused on a single platform, and you
set out to decide among DOS; UNIX; the Macintosh; and Windows, Windows NT, and OS/2.</P>
<P>You have many painful meetings with Jim Grandiose, and it becomes clear that there
is no right choice, and so you decide to separate the front end, that is the user
interface or UI, from the back end, the communications and database part. To get
things going quickly, you decide to write for DOS first, followed by Win32, the Mac,
and then UNIX and OS/2.</P>
<P>This simple decision has enormous ramifications for your project. It quickly becomes
obvious that you will need a class library or a series of libraries to handle memory
management, the various user interfaces, and perhaps also the communications and
database components.</P>
<P>Mr. Grandiose believes strongly that projects live or die by having one person
with a clear vision, so he asks that you do the initial architectural analysis and
design before hiring any programmers. You set out to analyze the problem.
<H3 ALIGN="CENTER"><A NAME="Heading15"></A><FONT COLOR="#000077">Divide and Conquer</FONT></H3>
<P>It quickly becomes obvious that you really have more than one problem to solve.
You divide the project into these significant sub-projects:
<BR>
<DL>
<DD><B>1.</B> Communications: the ability for the software to dial into the e-mail
provider via modem, or to connect over a network.<BR>
<BR>
<B>2.</B> Database: the ability to store data and to retrieve it from disk.<BR>
<BR>
<B>3.</B> E-mail: the ability to read various e-mail formats and to write new messages
to each system.<BR>
<BR>
<B>4.</B> Editing: providing state-of-the-art editors for the creation and manipulation
of messages.<BR>
<BR>
<B>5.</B> Platform issues: the various UI issues presented by each platform (DOS,
Macintosh, and so on).<BR>
<BR>
<B>6.</B> Extensibility: planning for growth and enhancements.<BR>
<BR>
<B>7.</B> Organization and scheduling: managing the various developers and their
code interdependencies. Each group must devise and publish schedules, and then be
able to plan accordingly. Senior management and marketing need to know when the product
will be ready.
</DL>
<BR>
<P>You decide to hire a manager to handle item 7, organization and scheduling. You
then hire senior developers to help you analyze and design, and then to manage the
implementation of the remaining areas. These senior developers will create the following
teams:
<BR>
<DL>
<DD><B>1.</B> Communications: responsible for both dial-up and network communications.
They deal with packets, streams, and bits, rather than with e-mail messages per se.<BR>
<BR>
<B>2.</B> Message format: responsible for converting messages from each e-mail provider
to a canonical form (PostMaster standard) and back. It is also their job to write
these messages to disk and to get them back off the disk as needed.<BR>
<BR>
<B>3.</B> Message editors: This group is responsible for the entire UI of the product,
on each platform. It is their job to ensure that the interface between the back end
and the front end of the product is sufficiently narrow that extending the product
to other platforms does not require duplication of code.
</DL>
<BR>
<H3 ALIGN="CENTER"><A NAME="Heading16"></A><FONT COLOR="#000077">Message Format</FONT></H3>
<P>You decide to focus on the message format first, setting aside the issues relating
to communications and user interface. These will follow once you understand more
fully what it is you are dealing with. There is little sense in worrying about how
to present the information to the user until you understand what information you
are dealing with.</P>
<P>An examination of the various e-mail formats reveals that they have many things
in common, despite their various differences. Each e-mail message has a point of
origination, a destination, and a creation date. Nearly all such messages have a
title or subject line and a body which may consist of simple text, rich text (text
with formatting), graphics, and perhaps even sound or other fancy additions. Most
such e-mail services also support attachments, so that users can send programs and
other files.</P>
<P>You confirm your early decision that you will read each mail message out of its
original format and into PostMaster format. This way you will only have to store
one record format, and writing to and reading from the disk will be simplified. You
also decide to separate the "header" information (sender, recipient, date,
title, and so on) from the body of the message. Often the user will want to scan
the headers without necessarily reading the contents of all the messages. You anticipate
that a time may come when users will want to download only the headers from the message
provider, without getting the text at all, but for now you intend that version 1
of PostMaster will always get the full message, although it may not display it to
the user.
<H3 ALIGN="CENTER"><A NAME="Heading17"></A><FONT COLOR="#000077">Initial Class Design</FONT></H3>
<P>This analysis of the messages leads you to design the <TT>Message</TT> class.
In anticipation of extending the program to non-e-mail messages, you derive <TT>EmailMessage</TT>
from the abstract base <TT>Message</TT>. From <TT>EmailMessage</TT> you derive <TT>PostMasterMessage</TT>,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -