[Page 1528 (
continued
)]
J.2. Class
ATM
Class
ATM
(Fig. J.1) represents the ATM as a whole. Lines 511 implement the class's attributes. We determine all but one of these attributes from the UML class diagrams of Fig. 11.21 and Fig. 11.22. Line 5 declares the
bool
attribute
userAuthenticated
from Fig. 11.22. Line 6 declares an attribute not found in our UML design
int
attribute
currentAccountNumber
, which keeps track of the account number of the current authenticated
user
. Lines 711 declare reference-type instance
variables
corresponding to the
ATM
class's associations
modeled
in the class diagram of Fig. 11.21. These attributes allow the ATM to access its
parts
(i.e., its
Screen
,
Keypad
,
CashDispenser
and
DepositSlot
) and interact with the bank's account information database (i.e., a
BankDatabase
object).
Figure J.1. Class
ATM
represents the ATM.
1
// ATM.cs
2
// Represents an automated teller machine.
3
public class
ATM
4
{
5
private bool
userAuthenticated;
// true if user is authenticated
6
private int
currentAccountNumber;
// user's account number
7
private
Screen screen;
// reference to ATM's screen
8
private
Keypad keypad;
// reference to ATM's keypad
9
private
CashDispenser cashDispenser;
// ref to ATM's cash
dispenser
10
private
DepositSlot depositSlot;
// reference to ATM's deposit slot
11
private
BankDatabase bankDatabase;
// ref to account
info
database
12
13
// enumeration that represents main menu options
14
private enum
MenuOption
15
{
16
BALANCE_INQUIRY
=
1
,
17
WITHDRAWAL
=
2
,
18
DEPOSIT
=
3
,
19
EXIT_ATM
=
4
20
}
// end enum MenuOption
21
[Page 1529]
22
// parameterless constructor initializes instance variables
23
public
ATM()
24
{
25
userAuthenticated =
false
;
// user is not authenticated to start
26
currentAccountNumber =
;
// no current account number to start
27
screen =
new
Screen();
// create screen
28
keypad =
new
Keypad();
// create keypad
29
cashDispenser =
new
CashDispenser();
// create cash dispenser
30
depositSlot =
new
DepositSlot();
// create deposit slot
31
bankDatabase =
new
BankDatabase();
// create account info database
32
}
// end constructor
33
34
// start ATM
35
public void
Run()
36
{
37
// welcome and authenticate users; perform transactions
38
while
(
true
)
// infinite loop
39
{
40
// loop while user is not yet authenticated
41
while
( !userAuthenticated )
42
{
43
screen.DisplayMessageLine(
"\nWelcome!"
);
44
AuthenticateUser();
// authenticate user
45
}
// end while
46
47
PerformTransactions();
// for authenticated user
48
userAuthenticated =
false
;
// reset before
next
ATM session
49
currentAccountNumber =
;
// reset before next ATM session
50
screen.DisplayMessageLine(
"\nThank you!
Goodbye
!"
);
51
}
// end while
52
}
// end method Run
53
54
// attempt to authenticate user against database
55
private void
AuthenticateUser()
56
{
57
// prompt for account number and input it from user
58
screen.DisplayMessage(
"\nPlease enter your account number: "
);
59
int
accountNumber = keypad.GetInput();
60
61
// prompt for PIN and input it from user
62
screen.DisplayMessage(
"\nEnter your PIN: "
);
63
int
pin = keypad.GetInput();
64
65
// set userAuthenticated to boolean value returned by database
66
userAuthenticated =
67
bankDatabase.AuthenticateUser( accountNumber, pin );
68
69
// check whether authentication succeeded
70
if
( userAuthenticated )
71
currentAccountNumber = accountNumber;
// save user's account #
[Page 1530]
72
else
73
screen.DisplayMessageLine(
74
"Invalid account number or PIN. Please try again."
);
75
}
// end method AuthenticateUser
76
77
// display the main menu and perform transactions
78
private void
PerformTransactions()
79
{
80
Transaction currentTransaction;
// transaction being
processed
81
bool
userExited =
false
;
// user has not
chosen
to exit
82
83
// loop while user has not chosen exit option
84
while
( !userExited )
85
{
86
// show main menu and get user selection
87
int
mainMenuSelection = DisplayMainMenu();
88
89
// decide how to proceed based on user's menu selection
90
switch
( ( MenuOption ) mainMenuSelection )
91
{
92
// user chooses to perform one of three transaction types
93
case
MenuOption.BALANCE_INQUIRY
:
94
case
MenuOption.WITHDRAWAL
:
95
case
MenuOption.DEPOSIT
:
96
// initialize as new object of chosen type
97
currentTransaction =
98
CreateTransaction( mainMenuSelection );
99
currentTransaction.Execute();
// execute transaction
100
break
;
101
case
MenuOption.EXIT_ATM
:
// user chose to terminate session
102
screen.DisplayMessageLine(
"\nExiting the system..."
);
103
userExited =
true
;
// this ATM session should end
104
break
;
105
default
:
// user did not enter an integer from 1-4
106
screen.DisplayMessageLine(
107
"\nYou did not enter a valid selection. Try again."
);
108
break
;
109
}
// end switch
110
}
// end while
111
}
// end method PerformTransactions
112
113
// display the main menu and return an input selection
114
private int
DisplayMainMenu()
115
{
116
screen.DisplayMessageLine(
"\nMain menu:"
);
117
screen.DisplayMessageLine(
"1 - View my balance"
);
118
screen.DisplayMessageLine(
"2 - Withdraw cash"
);
119
screen.DisplayMessageLine(
"3 - Deposit funds"
);
120
screen.DisplayMessageLine(
"4 - Exit\n"
);
121
screen.DisplayMessage(
"Enter a choice: "
);
122
return
keypad.GetInput();
// return user's selection
123
}
// end method DisplayMainMenu
[Page 1531]
124
125
// return object of specified Transaction derived class
126
private
Transaction CreateTransaction(
int
type )
127
{
128
Transaction temp =
null
;
// null Transaction reference
129
130
// determine which type of Transaction to create
131
switch
( ( MenuOption ) type )
132
{
133
// create new BalanceInquiry transaction
134
case
MenuOption.BALANCE_INQUIRY
:
135
temp =
new
BalanceInquiry( currentAccountNumber,
136
screen, bankDatabase);
137
break
;
138
case
MenuOption.WITHDRAWAL
:
// create new Withdrawal transaction
139
temp =
new
Withdrawal( currentAccountNumber, screen,
140
bankDatabase, keypad, cashDispenser);
141
break
;
142
case
MenuOption.DEPOSIT
:
// create new Deposit transaction
143
temp =
new
Deposit( currentAccountNumber, screen,
144
bankDatabase, keypad, depositSlot);
145
break
;
146
}
// end switch
147
148
return
temp;
149
}
// end method CreateTransaction
150
}
// end class ATM
|
Lines 1420 declare an enumeration that corresponds to the four options in the ATM's main menu (i.e., balance inquiry, withdrawal, deposit and exit). Lines 2332 declare class
ATM
's constructor, which initializes the class's attributes. When an
ATM
object is first created, no user is authenticated, so line 25 initializes
userAuthenticated
to
false
. Line 26 initializes
currentAccountNumber
to
because there is no current user yet. Lines 2730 instantiate new objects to represent the parts of the ATM. Recall that class
ATM
has composition relationships with classes
Screen
,
Keypad
,
CashDispenser
and
DepositSlot
, so class
ATM
is responsible for their creation. Line 31 creates a new
BankDatabase
. As you will soon see, the
BankDatabase
creates two
Account
objects that can be used to test the ATM. [
Note:
If this were a real ATM system, the
ATM
class would receive a reference to an existing database object created by the bank. However, in this implementation, we are only simulating the bank's database, so class
ATM
creates the
BankDatabase
object with which it
interacts
.]
Implementing the Operation
The class diagram of Fig. 11.22 does not list any operations for class
ATM
. We now implement one operation (i.e.,
public
method) in class
ATM
that allows an external client of the class (i.e., class
ATMCaseStudy
; Section J.13) to tell the
ATM
to run.
ATM
method
Run
(lines 3552) uses an infinite loop (lines 3851) to repeatedly welcome a user, attempt to authenticate the user and, if authentication succeeds, allow the user to perform transactions. After an authenticated user
performs
the desired transactions and exits, the ATM resets itself, displays a goodbye message and restarts the process for the next user. We use an infinite loop here to simulate the fact that an ATM appears to run continuously until the bank turns it off (an action beyond the user's control). An ATM user can exit the system, but cannot
turn
off the ATM completely.
[Page 1532]
Inside method
Run
's infinite loop, lines 4145 cause the ATM to repeatedly welcome and attempt to authenticate the user as long as the user has not been authenticated (i.e., the condition
!userAuthenticated
is
true
). Line 43 invokes method
DisplayMessageLine
of the
ATM
's
screen
to display a welcome message. Like
Screen
method
DisplayMessage
designed in the case study, method
DisplayMessageLine
(declared in lines 1417 of Fig. J.2) displays a message to the user, but this method also outputs a newline after displaying the message. We add this method during implementation to give class
Screen
's
clients
more control over the placement of displayed messages. Line 44 invokes class
ATM
's
private
utility method
AuthenticateUser
(declared in lines 5575) to attempt to authenticate the user.
Figure J.2. Class
Screen
represents the screen of the ATM.
(This item is displayed on pages 1534 - 1535 in the print version)
1
// Screen.cs
2
// Represents the screen of the ATM
3
using
System;
4
5
public class
Screen
6
{
7
// displays a message without a terminating
carriage
return
8
public void
DisplayMessage(
string
message )
9
{
10
Console.Write( message );
11
}
// end method DisplayMessage
12
13
// display a message with a terminating carriage return
14
public void
DisplayMessageLine(
string
message )
15
{
16
Console.WriteLine( message );
17
}
// end method DisplayMessageLine
18
[Page 1535]
19
// display a dollar amount
20
public void
DisplayDollarAmount(
decimal
amount )
21
{
22
Console.Write(
"{0:C}"
, amount );
23
}
// end method DisplayDollarAmount
24
}
// end class Screen
|
Authenticating the User
We refer to the requirements document to determine the steps necessary to authenticate the user before allowing transactions to occur. Line 58 of method
AuthenticateUser
invokes method
DisplayMessage
of the
ATM
's
screen
to prompt the user to enter an account number. Line 59 invokes method
GetInput
of the
ATM
's
keypad
to obtain the user's input, then stores this integer in local variable
accountNumber
. Method
AuthenticateUser
next prompts the user to enter a PIN (line 62), and stores the PIN in local variable
pin
(line 63). Next, lines 6667 attempt to authenticate the user by passing the
accountNumber
and
pin
entered by the user to the
bankDatabase
's
AuthenticateUser
method. Class
ATM
sets its
userAuthenticated
attribute to the
bool
value returned by this method
userAuthenticated
becomes
true
if authentication succeeds (i.e., the
accountNumber
and
pin
match those of an existing
Account
in
bankDatabase
) and remains
false
otherwise
. If
userAuthenticated
is
true
, line 71 saves the account number entered by the user (i.e.,
accountNumber
) in the ATM attribute
currentAccountNumber
. The other
methods
of class
ATM
use this variable whenever an ATM session requires access to the user's account number. If
userAuthenticated
is
false
, lines 7374 call the
screen
's
DisplayMessageLine
method to
indicate
that an invalid account number and/or PIN was entered, so the user must try again. Note that we set
currentAccountNumber
only after authenticating the user's account number and the associated PINif the database cannot authenticate the user,
currentAccountNumber
remains
.
After method
Run
attempts to authenticate the user (line 44), if
userAuthenticated
is still
false
(line 41), the
while
loop body (lines 4145) executes again. If
userAuthenticated
is now
true
, the loop terminates, and control continues with line 47, which calls class
ATM
's
private
utility method
PerformTransactions
.
Performing Transactions
Method
PerformTransactions
(lines 78111) carries out an ATM session for an authenticated user. Line 80 declares local variable
transaction
, to which we assign a
BalanceInquiry
,
Withdrawal
or
Deposit
object representing the ATM transaction currently being processed. Note that we use a
transaction
variable here to allow us to take advantage of polymorphism. Also, note that we name this variable after the role
name
included in the class diagram of Fig. 4.21
currentTransaction
. Line 81 declares another local variablea
bool
called
userExited
that keeps track of whether the user has chosen to exit. This variable controls a
while
loop (lines 84110) that allows the user to execute an unlimited number of transactions before choosing to exit. Within this loop, line 87 displays the main menu and obtains the user's menu selection by calling
ATM
utility method
DisplayMainMenu
(declared in lines 114123). This method displays the main menu by invoking methods of the
ATM
's
screen
and returns a menu selection obtained from the user through the
ATM
's
keypad
. Line 87 stores the user's selection, returned by
DisplayMainMenu
, in local variable
mainMenuSelection
.
[Page 1533]
After obtaining a main menu selection, method
PerformTransactions
uses a
switch
statement (lines 90109) to respond to the selection appropriately. If
mainMenuSelection
is equal to the underlying value of any of the three
enum
members
representing transaction types (i.e., if the user chose to perform a transaction), lines 9798 call utility method
CreateTransaction
(declared in lines 126149) to return a newly
instantiated
object of the type that corresponds to the selected transaction. Variable
currentTransaction
is assigned the reference returned by method
CreateTransaction
, then line 99 invokes method
Execute
of this transaction to execute it. We discuss
TRansaction
method
Execute
and the three
TRansaction
derived classes shortly. Note that we assign to the
TRansaction
variable
currentTransaction
an object of one of the three
transaction
derived classes so that we can execute transactions. For example, if the user chooses to perform a balance inquiry,
( MenuOption ) mainMenuSelection
(line 90) matches the case label
MenuOption.BALANCE_INQUIRY
, and
CreateTransaction
returns a
BalanceInquiry
object (lines 9798). Thus,
currentTransaction
refers to a
BalanceInquiry
and invoking
currentTransaction.Execute()
(line 99) results in
BalanceInquiry
's version of
Execute
being called polymorphically.
Creating Transactions
Method
CreateTransaction
(lines 126149) uses a
switch
statement (lines 131146) to instantiate a new
transaction
derived class object of the type indicated by the parameter
type
. Recall that method
PerformTransactions
passes
mainMenuSelection
to method
CreateTransaction
only when
mainMenuSelection
contains a value corresponding to one of the three transaction types. So parameter
type
(line 126) receives one of the values
MenuOption.BALANCE_INQUIRY
,
MenuOption.WITHDRAWAL
or
MenuOption.DEPOSIT
. Each
case
in the
switch
statement instantiates a new object by calling the appropriate
TRansaction
derived class constructor. Note that each constructor has a unique parameter list, based on the specific data required to initialize the derived class object. A
BalanceInquiry
(lines 135136) requires only the account number of the current user and references to the
ATM
's
screen
and the
bankDatabase
. In addition to these parameters, a
Withdrawal
(lines 139140) requires references to the
ATM
's
keypad
and
cashDispenser
, and a
Deposit
(lines 143144) requires references to the
ATM
's
keypad
and
depositSlot
. We discuss the transaction classes in detail in Sections J.9J.12.
After executing a transaction (line 99 in method
PerformTransactions
),
userExited
remains
false
, and the
while
loop in lines 84110 repeats, returning the user to the main menu. However, if a user does not perform a transaction and instead selects the main menu option to exit, line 103 sets
userExited
to
TRue
,
causing
the condition in line 84 of the
while
loop (
!userExited
) to become
false
. This
while
is the final statement of method
PerformTransactions
, so control returns to line 47 of the calling method
Run
. If the user enters an invalid main menu selection (i.e., not an integer in the range 14), lines 106107 display an appropriate error message,
userExited
remains
false
(as set in line 81) and the user returns to the main menu to try again.
[Page 1534]
When method
PerformTransactions
returns control to method
Run
, the user has chosen to exit the system, so lines 4849 reset the
ATM
's attributes
userAuthenticated
and
currentAccountNumber
to
false
and
, respectively, to prepare for the next ATM user. Line 50 displays a goodbye message to the current user before the ATM
welcomes
the next user.
|