Documente Academic
Documente Profesional
Documente Cultură
No se puede trabajar
en lo abstracto.
I. M. Pei
Objetivos
En este captulo aprender a:
Incorporar la herencia en el
diseo del ATM.
Incorporar el polimorfismo
en el diseo del ATM.
Estudiar un recorrido de
cdigo detallado del sistema
de software del ATM que
explica las cuestiones
de implementacin.
13.2
13.1
Introduccin
13.2
13.3
Incorporacin de la herencia y el
polimorfismo en el sistema ATM
13.4
13.4.4
13.4.5
13.4.6
13.4.7
13.4.8
13.4.9
13.4.10
13.4.11
13.4.12
13.5
511
La clase DispensadorEfectivo
La clase RanuraDeposito
La clase Cuenta
La clase BaseDatosBanco
La clase Transaccion
La clase SolicitudSaldo
La clase Retiro
La clase Deposito
La clase CasoEstudioATM
Conclusin
13.1 Introduccin
En el captulo 12 desarrollamos un diseo orientado a objetos para nuestro sistema ATM. Ahora implementaremos nuestro diseo orientado a objetos en Java. En la seccin 13.2 le mostraremos cmo convertir
los diagramas de clases en cdigo de Java. En la seccin 13.3 optimizaremos el diseo mediante la herencia
y el polimorfismo. Despus le presentaremos una implementacin completa en cdigo de Java del software
del ATM en la seccin 13.4. El cdigo contiene muchos comentarios cuidadosamente elaborados, y el
anlisis de la implementacin es detallado y preciso. Al estudiar esta aplicacin, usted tendr la oportunidad de ver una aplicacin ms substancial, del tipo que probablemente encontrar en la industria.
Visibilidad
Ahora aplicaremos modificadores de acceso a los miembros de nuestras clases. Ya presentamos en un captulo anterior los modificadores de acceso public y private. Los modificadores de acceso determinan
la visibilidad, o accesibilidad, de los atributos y mtodos de un objeto para otros objetos. Antes de empezar a implementar nuestro diseo, debemos considerar cules atributos y mtodos de nuestras clases
deben ser public y cules deben ser private.
Ya hemos observado que, por lo general los atributos deben ser private, y que los mtodos invocados
por los clientes de una clase dada deben ser public. Los mtodos que se llaman slo por otros mtodos
de la clase como mtodos utilitarios deben ser private. UML emplea marcadores de visibilidad para
modelar la visibilidad de los atributos y las operaciones. La visibilidad pblica se indica mediante la colocacin de un signo ms (+) antes de una operacin o atributo, mientras que un signo menos () indica
una visibilidad privada. La figura 13.1 muestra nuestro diagrama de clases actualizado, en el cual se incluyen los marcadores de visibilidad. [Nota: no incluimos parmetros de operacin en la figura 13.1; esto
es perfectamente normal. Agregar los marcadores de visibilidad no afecta a los parmetros que ya estn
modelados en los diagramas de clases de las figuras 12.17 a 12.21].
Navegabilidad
Antes de empezar a implementar nuestro diseo en Java, presentaremos una notacin adicional de
UML. El diagrama de clases de la figura 13.2 refina an ms las relaciones entre las clases del sistema
ATM, al agregar flechas de navegabilidad a las lneas de asociacin. Las flechas de navegabilidad (representadas como flechas con puntas delgadas ( ) en el diagrama de clases) indican en qu direccin
512
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
Cuenta
ATM
usuarioAutenticado : Boolean = false
SolicitudSaldo
numeroCuenta : Integer
+ ejecutar()
numeroCuenta : Integer
nip : Integer
saldoDisponible : Double
saldoTotal : Double
+ validarNIP : Boolean
+ obtenerSaldoDisponible() : Double
+ obtenerSaldoTotal() : Double
+ abonar()
+ cargar()
Retiro
numeroCuenta : Integer
monto : Double
+ ejecutar()
Pantalla
+ mostrarMensaje()
Deposito
Teclado
numeroCuenta : Integer
monto : Double
+ ejecutar()
+ obtenerEntrada() : Integer
DispensadorEfectivo
BaseDatosBanco
+ dispensarEfectivo()
+ haySuficienteEfectivoDisponible() : Boolean
RanuraDeposito
+ seRecibioSobreDeposito : Boolean
puede recorrerse una asociacin. Al implementar un sistema diseado mediante el uso de UML, los
programadores utilizan flechas de navegabilidad para ayudar a determinar cules objetos necesitan referencias a otros objetos. Por ejemplo, la flecha de navegabilidad que apunta de la clase ATM a la clase
BaseDatosBanco indica que podemos navegar de una a la otra, con lo cual se permite a la clase ATM
invocar a las operaciones de BaseDatosBanco. No obstante, como la figura 13.2 no contiene una flecha
de navegabilidad que apunte de la clase BaseDatosBanco a la clase ATM, la clase BaseDatosBanco no
puede acceder a las operaciones de la clase ATM. Las asociaciones en un diagrama de clases que tienen flechas de navegabilidad en ambos extremos, o que no tienen ninguna flecha, indican una navegabilidad
bidireccional: la navegacin puede proceder en cualquier direccin a lo largo de la asociacin.
Al igual que el diagrama de clases de la figura 12.10, el de la figura 13.2 omite las clases SolicitudSaldo y Deposito para simplificarlo. La navegabilidad de las asociaciones en las que participan estas dos
clases se asemeja mucho a la navegabilidad de las asociaciones de la clase Retiro. En la seccin 12.3 vimos
que SolicitudSaldo tiene una asociacin con la clase Pantalla. Podemos navegar de la clase SolicitudSaldo a la clase Pantalla a lo largo de esta asociacin, pero no podemos navegar de la clase Pantalla
a la clase SolicitudSaldo. Por ende, si modelramos la clase SolicitudSaldo en la figura 13.2, colocaramos una flecha de navegabilidad en el extremo de la clase Pantalla de esta asociacin. Recuerde
13.2
513
1
Teclado
DispensadorEfectivo
RanuraDeposito
Pantalla
1
1
0..1
Ejecuta
ATM
1
0..1
0..1
Retiro
0..1
0..1
1
Autentica al usuario contra
1
1
BaseDatosBanco
1
Contiene
0..*
Cuenta
tambin que la clase Deposito se asocia con las clases Pantalla, Teclado y RanuraDeposito. Podemos
navegar de la clase Deposito a cada una de estas clases, pero no al revs. Por lo tanto, podramos colocar flechas de navegabilidad en los extremos de las clases Pantalla, Teclado y RanuraDeposito de estas
asociaciones. [Nota: modelaremos estas clases y asociaciones adicionales en nuestro diagrama de clases
final en la seccin 13.3, una vez que hayamos simplificado la estructura de nuestro sistema, al incorporar el concepto orientado a objetos de la herencia].
514
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
produce el cdigo de la figura 13.3. Si encontramos que las variables de instancia de la clase
slo requieren la inicializacin predeterminada, eliminaremos el constructor sin parmetros
vaco, ya que es innecesario.
public Retiro()
{
} // fin del constructor de Retiro sin argumentos
7
8
Fig. 13.3 Cdigo de Java para la clase Retiro, con base en las figuras 13.1 y 13.2.
2. Use los atributos que se localizan en el segundo compartimiento para declarar las variables
de instancia. Por ejemplo, los atributos private numeroCuenta y monto de la clase Retiro
producen el cdigo de la figura 13.4. [Nota: el constructor de la versin funcional completa
de esta clase asignar valores a estos atributos].
1
// atributos
7
8
public Retiro()
10
11
12
{
} // fin del constructor de Retiro sin argumentos
} // fin de la clase Retiro
Fig. 13.4 Cdigo de Java para la clase Retiro, con base en las figuras 13.1 y 13.2.
3. Use las asociaciones descritas en el diagrama de clases para declarar las referencias a otros objetos. Por ejemplo, de acuerdo con la figura 13.2, Retiro puede acceder a un objeto de la clase
Pantalla, a un objeto de la clase Teclado, a un objeto de la clase DispensadorEfectivo y a
un objeto de la clase BaseDatosBanco. Esto produce el cdigo de la figura 13.5. [Nota: el constructor de la versin funcional completa de esta clase inicializar estas variables de instancia
con referencias a objetos reales].
4. Use las operaciones que se localizan en el tercer compartimiento de la figura 13.1 para declarar
las armazones de los mtodos. Si todava no hemos especificado un tipo de valor de retorno para
una operacin, declaramos el mtodo con el tipo de retorno void. Consulte los diagramas de
clases de las figuras 12.17 a 12.21 para declarar cualquier parmetro necesario. Por ejemplo,
al agregar la operacin public ejecutar en la clase Retiro, que tiene una lista de parmetros
vaca, se produce el cdigo de la figura 13.6. [Nota: codificaremos los cuerpos de los mtodos cuando implementemos el sistema ATM completo en la seccin 13.4].
Esto concluye nuestra discusin sobre los fundamentos de la generacin de clases a partir de diagramas
de UML.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
515
Fig. 13.5 Cdigo de Java para la clase Retiro, con base en las figuras 13.1 y 13.2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Fig. 13.6 Cdigo de Java para la clase Retiro, con base en las figuras 13.1 y 13.2.
516
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
13.2
13.3
Escriba cdigo de Java para empezar a implementar el diseo para la clase Teclado.
SolicitudSaldo
- numeroCuenta : Integer
+ ejecutar()
Retiro
Deposito
- numeroCuenta : Integer
- monto : Double
- numeroCuenta : Integer
- monto : Double
+ ejecutar()
+ ejecutar()
Generalizacin
UML especifica una relacin conocida como generalizacin para modelar la herencia. La figura 13.8
es el diagrama de clases que modela la generalizacin de la superclase Transaccion y las subclases
517
SolicitudSaldo, Retiro y Deposito. Las flechas con puntas triangulares huecas indican que las clases SolicitudSaldo, Retiro y Deposito extienden a la clase Transaccion. Se dice que la clase Transaccion es una generalizacin de las clases SolicitudSaldo, Retiro y Deposito. Se dice que las clases
SolicitudSaldo, Retiro y Deposito son especializaciones de la clase Transaccion.
Transaccin
numeroCuenta: Integer
+ obtenerNumeroCuenta()
+ ejecutar()
SolicitudSaldo
+ ejecutar()
Retiro
Deposito
monto : Double
monto : Double
+ ejecutar()
+ ejecutar()
Fig. 13.8 Diagrama de clases que modela la generalizacin de la superclase Transaccion y las subclases
SolicitudSaldo, Retiro y Deposito. Los nombres de las clases abstractas (por ejemplo, Transaccion)
y los nombres de los mtodos (por ejemplo, ejecutar en la clase Transaccion) aparecen en cursiva.
Las clases SolicitudSaldo, Retiro y Deposito comparten el atributo entero numeroCuenta, por lo
que factorizamos este atributo comn y lo colocamos en la superclase Transaccion. Ya no listamos a
numeroCuenta en el segundo compartimiento de cada subclase, puesto que las tres subclases heredan este
atributo de Transaccion. Sin embargo, recuerde que las subclases no pueden acceder de manera directa
a los atributos private de una superclase. Por lo tanto, incluimos el mtodo public obtenerNumeroCuenta en la clase Transaccion. Cada subclase heredar este mtodo, con lo cual podr acceder a su
numeroCuenta segn sea necesario para ejecutar una transaccin.
De acuerdo con la figura 13.7, las clases SolicitudSaldo, Retiro y Deposito tambin comparten la operacin ejecutar, por lo que colocamos el mtodo public ejecutar en la superclase Transaccion. Sin embargo, no tiene sentido implementar a ejecutar en la clase Transaccion, ya que la
funcionalidad que proporciona este mtodo depende del tipo de la transaccin actual. Por lo tanto, declaramos el mtodo ejecutar como abstract en la superclase Transaccion. Cualquier clase que contenga cuando menos un mtodo abstracto tambin debe declararse como abstract. Esto obliga a que
cualquier clase de Transaccion que deba ser una clase concreta (es decir, SolicitudSaldo, Retiro y
Deposito) a implementar el mtodo ejecutar. UML requiere que coloquemos los nombres de clase
abstractos (y los mtodos abstractos) en cursivas, por lo cual Transaccion y su mtodo ejecutar aparecen en cursivas en la figura 13.8. Observe que el mtodo ejecutar no est en cursivas en las subclases
SolicitudSaldo, Retiro y Deposito. Cada subclase sobrescribe el mtodo ejecutar de la superclase
Transaccion con una implementacin concreta que realiza los pasos apropiados para completar ese
tipo de transaccin. La figura 13.8 incluye la operacin ejecutar en el tercer compartimiento de las
clases SolicitudSaldo, Retiro y Deposito, ya que cada clase tiene una implementacin concreta distinta del mtodo sobrescrito.
518
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
Transaccion para
SolicitudSaldo.
invocar el mtodo
ejecutar,
ejecutar
de
Este enfoque polimrfico tambin facilita la extensibilidad del sistema. Si deseamos crear un nuevo
tipo de transaccin (por ejemplo, una transferencia de fondos o el pago de un recibo), slo tenemos
que crear una subclase de Transaccion adicional que sobrescriba el mtodo ejecutar con una versin
apropiada para ejecutar el nuevo tipo de transaccin. Slo tendramos que realizar pequeas modificaciones al cdigo del sistema, para permitir que los usuarios seleccionen el nuevo tipo de transaccin
del men principal y para que la clase ATM cree instancias y ejecute objetos de la nueva subclase. La clase
ATM podra ejecutar transacciones del nuevo tipo utilizando el cdigo actual, ya que ste ejecuta todas
las transacciones de manera polimrfica, usando una referencia Transaccion general.
Cabe recordar que una clase abstracta como Transaccion es una para la cual el programador nunca tendr la intencin de crear instancias de objetos. Una clase abstracta slo declara los atributos
y comportamientos comunes de sus subclases en una jerarqua de herencia. La clase Transaccion define el concepto de lo que significa ser una transaccin que tiene un nmero de cuenta y puede ejecutarse. Tal vez usted se pregunte por qu nos tomamos la molestia de incluir el mtodo abstract
ejecutar en la clase Transaccion, si carece de una implementacin concreta. En concepto, incluimos
este mtodo porque corresponde al comportamiento que define a todas las transacciones: ejecutarse.
Tcnicamente, debemos incluir el mtodo ejecutar en la superclase Transaccion, de manera que
la clase ATM (o cualquier otra clase) pueda invocar mediante el polimorfismo a la versin sobrescrita
de este mtodo en cada subclase, a travs de una referencia Transaccion. Adems, desde la perspectiva de la ingeniera de software, al incluir un mtodo abstracto en una superclase, el que implementa
las subclases se ve obligado a sobrescribir ese mtodo con implementaciones concretas en las subclases, o de lo contrario, las subclases tambin sern abstractas, lo cual impedir que se creen instancias
de objetos de esas subclases.
519
1
Teclado
DispensadorEfectivo
1
RanuraDeposito
Pantalla
0..1
Retiro
1
1
0..1
Ejecuta
ATM
1
0..1
0..1
Transaccin
0..1
0..1
Deposito
0..1
1
Autentica al usuario contra
1
SolicitudSaldo
1
BaseDatosBanco
1
Contiene
0..*
Cuenta
Fig. 13.9 Diagrama de clases del sistema ATM (en el que se incorpora la herencia). El nombre de la clase abstracta
Transaccion aparece en cursivas.
Tambin agregamos una asociacin entre la clase Transaccion y la clase BaseDatosBanco (figura
13.9). Todos los objetos Transaccion requieren una referencia a BaseDatosBanco, de manera que puedan acceder a (y modificar) la informacin de las cuentas. Debido a que cada subclase de Transaccion
hereda esta referencia, ya no tenemos que modelar la asociacin entre la clase Retiro y BaseDatosBanco.
De manera similar, ya no existen las asociaciones entre BaseDatosBanco y las clases SolicitudSaldo y
Deposito, que omitimos anteriormente.
Mostramos una asociacin entre la clase Transaccion y la clase Pantalla. Todos los objetos
Transaccion muestran los resultados al usuario a travs de la Pantalla. Por ende, ya no incluimos
la asociacin que modelamos antes entre Retiro y Pantalla, aunque Retiro an participa en las asociaciones con DispensadorEfectivo y Teclado. Nuestro diagrama de clases que incorpora la herencia
tambin modela a Deposito y SolicitudSaldo. Mostramos las asociaciones entre Deposito y tanto
RanuraDeposito como Teclado. La clase SolicitudSaldo no participa en asociaciones ms que las
heredadas de la clase Transaccion; un objeto SolicitudSaldo slo necesita interactuar con la BaseDatosBanco y con la Pantalla.
La figura 13.1 muestra los atributos y las operaciones con marcadores de visibilidad. Ahora presentamos un diagrama de clases modificado que incorpora la herencia en la figura 13.10. Este diagrama
abreviado no muestra las relaciones de herencia, sino los atributos y los mtodos despus de haber
empleado la herencia en nuestro sistema. Para ahorrar espacio, como hicimos en la figura 12.12, no in-
520
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
cluimos los atributos mostrados por las asociaciones en la figura 13.9; sin embargo, los incluimos en la
implementacin en Java que aparece en la seccin 13.4. Tambin omitimos todos los parmetros de
las operaciones, como hicimos en la figura 13.1; al incorporar la herencia no se afectan los parmetros
que ya estaban modelados en las figuras 12.17 a 12.21.
ATM
usuarioAutenticado : Boolean = false
Transaccin
numeroCuenta : Integer
+ obtenerNumeroCuenta()
+ ejecutar()
SolicitudSaldo
+ ejecutar()
Cuenta
numeroCuenta : Integer
nip : Integer
saldoDisponible : Double
saldoTotal : Double
+ validarNIP() : Boolean
+ obtenerSaldoDisponible() : Double
+ obtenerSaldoTotal() : Double
+ abonar()
+ cargar()
Pantalla
+ mostrarMensaje()
Retiro
Teclado
monto : Double
+ ejecutar()
+ obtenerEntrada() : Integer
Deposito
monto : Double
+ ejecutar()
DispensadorEfectivo
cuenta : Integer = 500
+ dispensarEfectivo()
+ haySuficienteEfectivoDisponible() : Boolean
BaseDatosBanco
RanuraDeposito
+ autenticarUsuario() : Boolean
+ obtenerSaldoDisponible() : Double
+ obtenerSaldoTotal() : Double
+ abonar()
+ cargar()
+ seRecibioSobre() : Boolean
Fig. 13.10 Diagrama de clases con atributos y operaciones (incorporando la herencia). El nombre de la
clase abstracta Transaccion y el nombre del mtodo abstracto ejecutar en la clase Transaccion aparecen
en cursiva.
521
Implementacin del diseo del sistema ATM (en el que se incorpora la herencia)
En la seccin 13.2 empezamos a implementar el diseo del sistema ATM en cdigo de Java. Ahora
modificaremos nuestra implementacin para incorporar la herencia, usando la clase Retiro como
ejemplo.
1. Si la clase A es una generalizacin de la clase B, entonces la clase B extiende a la clase A en la declaracin de la clase. Por ejemplo, la superclase abstracta Transaccion es una generalizacin de
la clase Retiro. La figura 13.11 muestra la declaracin de la clase Retiro.
1
// Retiro.java
// atributos
9
10
11
public Retiro()
12
13
14
Fig. 13.12 Cdigo de Java para la clase Retiro, basada en las figuras 13.9 y 13.10 (parte 1 de 2).
522
15
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
// mtodo que sobrescribe a ejecutar
16
@Override
17
18
19
20
Fig. 13.12 Cdigo de Java para la clase Retiro, basada en las figuras 13.9 y 13.10 (parte 2 de 2).
Felicidades por haber completado la porcin correspondiente al diseo del caso de estudio!
En la seccin 13.4 implementamos el sistema ATM, en cdigo en Java. Le recomendamos leer con
cuidado el cdigo y su descripcin. El cdigo contiene muchos comentarios y sigue con precisin
el diseo, con el cual usted ya est familiarizado. La descripcin que lo acompaa est escrita cuidadosamente, para guiar su comprensin acerca de la implementacin con base en el diseo de UML.
Dominar este cdigo es un maravilloso logro culminante, despus de estudiar las secciones 12.2 a 12.7
y 13.2 a 13.3.
13.5 Indique si el siguiente enunciado es verdadero o falso y, si es falso, explique por qu: UML requiere que subrayemos los nombres de las clases abstractas y los nombres de los mtodos abstractos.
13.6 Escriba cdigo en Java para empezar a implementar el diseo para la clase Transaccion que se especifica en las
figuras 13.9 y 13.10. Asegrese de incluir los atributos tipo referencias private, con base en las asociaciones de la clase
Transaccion. Asegrese tambin de incluir los mtodos establecer public que proporcionan acceso a cualquiera de
estos atributos private que requieren las subclases para realizar sus tareas.
13.4
523
una parte normal del proceso de diseo orientado a objetos. A medida que implementamos el sistema,
completamos la lgica del programa, agregando atributos y comportamientos segn sea necesario para
construir el sistema ATM especificado por el documento de requerimientos de la seccin 12.2.
Concluimos el anlisis presentando una aplicacin de Java (CasoEstudioATM) que inicia el ATM
y pone en uso las dems clases del sistema. Recuerde que estamos desarrollando la primera versin del
sistema ATM que se ejecuta en una computadora personal, y utiliza el teclado y el monitor para lograr
la mayor semejanza posible con el teclado y la pantalla de un ATM. Adems, slo simulamos las acciones del dispensador de efectivo y la ranura de depsito del ATM. Sin embargo, tratamos de implementar
el sistema de manera tal que las versiones reales de hardware de esos dispositivos pudieran integrarse
sin necesidad de cambios considerables en el cdigo.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ATM.java
// Representa a un cajero automtico
public class ATM
{
private boolean usuarioAutenticado; // indica si el usuario es autenticado
private int numeroCuentaActual; // nmero de cuenta actual del usuario
private Pantalla pantalla; // pantalla del ATM
private Teclado teclado; // teclado del ATM
private DispensadorEfectivo dispensadorEfectivo; // dispensador de efectivo del ATM
private RanuraDeposito ranuraDeposito; // ranura de depsito del ATM
private BaseDatosBanco baseDatosBanco; // base de datos de informacin de las
cuentas
// constantes correspondientes a las opciones del men principal
private static final int SOLICITUD_SALDO = 1;
private static final int RETIRO = 2;
private static final int DEPOSITO = 3;
private static final int SALIR = 4;
// el constructor sin argumentos de ATM inicializa las variables de instancia
public ATM()
{
usuarioAutenticado = false; // al principio, el usuario no est autenticado
numeroCuentaActual = 0; // al principio, no hay nmero de cuenta
pantalla = new Pantalla(); // crea la pantalla
524
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
teclado = new Teclado(); // crea el teclado
dispensadorEfectivo = new DispensadorEfectivo(); // crea el dispensador de
efectivo
ranuraDeposito = new RanuraDeposito(); // crea la ranura de depsito
baseDatosBanco = new BaseDatosBanco(); // crea la base de datos de informacin
de cuentas
} // fin del constructor sin argumentos de ATM
// inicia el ATM
public void run()
{
// da la bienvenida al usuario y lo autentica; realiza transacciones
while ( true )
{
// itera mientras el usuario no haya sido autenticado
while ( !usuarioAutenticado )
{
pantalla.mostrarLineaMensaje( \nBienvenido! );
autenticarUsuario(); // autentica el usuario
} // fin de while
realizarTransacciones(); // ahora el usuario est autenticado
usuarioAutenticado = false; // restablece antes de la siguiente sesin con
el ATM
numeroCuentaActual = 0; // restablece antes de la siguiente sesin con el
ATM
pantalla.mostrarLineaMensaje( \nGracias! Adios! );
} // fin de while
} // fin del mtodo run
// trata de autenticar al usuario en la base de datos
private void autenticarUsuario()
{
pantalla.mostrarMensaje( \nEscriba su numero de cuenta: );
int numeroCuenta = teclado.obtenerEntrada(); // recibe como entrada el nmero
de cuenta
pantalla.mostrarMensaje( \nEscriba su NIP: ); // pide el NIP
int nip = teclado.obtenerEntrada(); // recibe como entrada el NIP
// establece usuarioAutenticado con el valor booleano devuelto por la base de
datos
usuarioAutenticado =
baseDatosBanco.autenticarUsuario( numeroCuenta, nip );
// verifica si la autenticacin tuvo xito
if ( usuarioAutenticado )
{
numeroCuentaActual = numeroCuenta; // guarda el # de cuenta del usuario
} // fin de if
else
pantalla.mostrarLineaMensaje(
Numero de cuenta o NIP invalido. Intente de nuevo. );
} // fin del mtodo autenticarUsuario
// muestra el men principal y realiza transacciones
private void realizarTransacciones()
{
// variable local para almacenar la transaccin que se procesa actualmente
Transaccion transaccionActual = null;
13.4
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
525
526
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
13.4
527
Realizar transacciones
El mtodo realizarTransacciones (lneas 75 a 112) lleva a cabo una sesin con el ATM para un usuario autenticado. La lnea 78 declara una variable local Transaccion a la que asignaremos un objeto
SolicitudSaldo, Retiro o Deposito, el cual representa la transaccin del ATM que el usuario seleccion. Aqu usaremos una variable Transaccion para que nos permita sacar provecho del polimorfismo.
Adems, nombramos a esta variable con base en el nombre de rol incluido en el diagrama de clases de
la figura 12.7: transaccionActual. La lnea 80 declara otra variable boolean llamada usuarioSalio, la
cual lleva el registro que indica si el usuario ha elegido salir o no. Esta variable controla un ciclo while
(lneas 83 a 111), el cual permite al usuario ejecutar un nmero ilimitado de transacciones antes de
que elija salir del sistema. Dentro de este ciclo, la lnea 86 muestra el men principal y obtiene la seleccin
del men del usuario al llamar a un mtodo utilitario de ATM, llamado mostrarMenuPrincipal (declarado en las lneas 115 a 124). Este mtodo muestra el men principal invocando a los mtodos de
la pantalla del ATM, y devuelve una seleccin del men que obtiene del usuario, a travs del teclado
del ATM. La lnea 86 almacena la seleccin del usuario devuelta por mostrarMenuPrincipal en la variable local seleccionMenuPrincipal.
Despus de obtener una seleccin del men principal, el mtodo realizarTransacciones usa
una instruccin switch (lneas 89 a 110) para responder a esa seleccin en forma apropiada. Si seleccionMenuPrincipal es igual a cualquiera de las tres constantes enteras que representan los tipos de
528
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
transacciones (es decir, si el usuario elige realizar una transaccin), las lneas 97 y 98 llaman al mtodo
utilitario crearTransaccion (declarado en las lneas 127 a 149 para regresar un objeto recin instanciado del tipo que corresponde a la transaccin seleccionada. A la variable transaccionActual se le
asigna la referencia devuelta por crearTransaccion, y despus la lnea 100 invoca al mtodo ejecutar
de esta transaccin para ejecutarla. En breve hablaremos sobre el mtodo ejecutar de Transaccin y
sobre las tres subclases de Transaccion. Asignamos a la variable transaccionActual de Transaccion
un objeto de una de las tres subclases de Transaccion, de modo que podamos ejecutar las transacciones mediante el polimorfismo. Por ejemplo, si el usuario opta por realizar una solicitud de saldo, seleccionMenuPrincipal es igual a SOLICITUD_SALDO, lo cual conduce a que crearTransaccion devuelva
un objeto SolicitudSaldo. Por ende, transaccionActual se refiere a una SolicitudSaldo, y la invocacin de transaccionActual.ejecutar() produce como resultado la invocacin a la versin de
ejecutar que corresponde a SolicitudSaldo.
13.4
529
// Pantalla.java
// Representa a la pantalla del ATM
public class Pantalla
{
// muestra un mensaje sin un retorno de carro
public void mostrarMensaje( String mensaje )
{
System.out.print( mensaje );
} // fin del mtodo mostrarMensaje
// muestra un mensaje con un retorno de carro
public void mostrarLineaMensaje( String mensaje )
{
System.out.println( mensaje );
} // fin del mtodo mostrarLineaMensaje
// muestra un monto en dlares
public void mostrarMontoDolares( double monto )
{
System.out.printf( $%,.2f, monto );
} // fin del mtodo mostrarMontoDolares
} // fin de la clase Pantalla
530
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
// Teclado.java
// Representa el teclado del ATM
import java.util.Scanner; // el programa usa a Scanner para obtener la entrada del
usuario
public class Teclado
{
private Scanner entrada; // lee datos de la lnea de comandos
// el constructor sin argumentos inicializa el objeto Scanner
public Teclado()
{
entrada = new Scanner( System.in );
} // fin del constructor sin argumentos de Teclado
// devuelve un valor entero introducido por el usuario
public int obtenerEntrada()
{
return entrada.nextInt(); // suponemos que el usuario introduce un entero
} // fin del mtodo obtenerEntrada
} // fin de la clase Teclado
no sea nmero entero. Puesto que el teclado del ATM real permite introducir slo enteros, vamos a
suponer que no ocurrir una excepcin y no intentaremos corregir este problema. Para obtener ms informacin sobre cmo atrapar excepciones, vea el captulo 11, Manejo de excepciones: un anlisis ms
profundo]. Recuerde que nextInt contiene toda la entrada utilizada por el ATM. El mtodo obtenerEntrada de Teclado slo devuelve el entero introducido por el usuario. Si un cliente de la clase Teclado
requiere entrada que cumpla con ciertos criterios (por decir, un nmero que corresponda a una opcin
vlida del men), el cliente deber realizar la comprobacin de errores.
// DispensadorEfectivo.java
Fig. 13.16 La clase DispensadorEfectivo representa al dispensador de efectivo del ATM (parte 1 de 2).
13.4
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
531
Fig. 13.16 La clase DispensadorEfectivo representa al dispensador de efectivo del ATM (parte 2 de 2).
El mtodo haySuficienteEfectivoDisponible (lneas 24 a 32) tiene un parmetro llamado
el cual especifica el monto de efectivo en cuestin. La lnea 26 calcula el nmero de billetes
de $20 que se requieren para dispensar el monto solicitado. El ATM permite al usuario elegir slo
montos de retiro que sean mltiplos de $20, por lo que dividimos monto entre 20 para obtener el nmero de billetesRequeridos. Las lneas 28 a 31 devuelven true si la cuenta del DispensadorEfectivo
es mayor o igual a billetesRequeridos (es decir, que haya suficientes billetes disponibles), y false
en caso contrario (que no haya suficientes billetes). Por ejemplo, si un usuario desea retirar $80 (que
billetesRequeridos sea 4) y slo quedan tres billetes (cuenta es 3), el mtodo devuelve false.
El mtodo dispensarEfectivo (lneas 17 a 21) simula el proceso de dispensar el efectivo. Si nuestro
sistema se conectara al hardware real de un dispensador de efectivo, este mtodo interactuara con el
dispositivo para dispensar fsicamente el efectivo. Nuestra versin del mtodo tan slo reduce la cuenta
de billetes restantes con base en el nmero requerido para dispensar el monto especificado (lnea 20).
Es responsabilidad del cliente de la clase (es decir, Retiro) informar al usuario que se dispens el efectivo; la clase DispensadorEfectivo no puede interactuar de manera directa con Pantalla.
monto,
532
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
una ranura de depsito. RanuraDeposito no tiene atributos y slo cuenta
Sobre (lneas 8 a 11), el cual indica si se recibi un sobre de depsito.
// RanuraDeposito.java
3
4
{
return true; // se recibi el sobre
10
11
12
En el documento de requerimientos vimos que el ATM permite al usuario hasta dos minutos para
insertar un sobre. La versin actual del mtodo seRecibioSobre slo devuelve true de inmediato (lnea
10), ya que sta es slo una simulacin de software, por lo que asumimos que el usuario insert un sobre dentro del lmite de tiempo requerido. Si se conectara el hardware de una ranura de depsito real a
nuestro sistema, podra implementarse el mtodo seRecibioSobre para esperar un mximo de dos
minutos a recibir una seal del hardware de la ranura de depsito, indicando que en definitiva el usuario
insert un sobre de depsito. Si seRecibioSobre recibiera dicha seal en un tiempo mximo de dos
minutos, el mtodo devolvera true. Si transcurrieran los dos minutos y el mtodo no recibiera ninguna
seal, entonces devolvera false.
// Cuenta.java
3
4
Fig. 13.18 La clase Cuenta representa a una cuenta bancaria (parte 1 de 2).
13.4
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
533
Fig. 13.18 La clase Cuenta representa a una cuenta bancaria (parte 2 de 2).
534
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
La clase Cuenta tiene un constructor (lneas 12 a 19) que recibe como argumentos un nmero de
cuenta, el NIP establecido para la cuenta, el saldo disponible inicial y el saldo total inicial de la cuenta.
Las lneas 15 a 18 asignan estos valores a los atributos de la clase (es decir, los campos).
El mtodo validarNIP (lneas 22 a 28) determina si un NIP especificado por el usuario (es decir,
el parmetro nipUsuario) coincide con el NIP asociado con la cuenta (es decir, el atributo nip). Recuerde que modelamos el parmetro nipUsuario de este mtodo en la figura 12.19. Si los dos NIP coinciden,
el mtodo devuelve true (lnea 25); en caso contrario devuelve false (lnea 27).
Los mtodos obtenerSaldoDisponible (lneas 31 a 34) y obtenerSaldoTotal (lneas 37 a 40)
devuelven los valores de los atributos double saldoDisponible y saldoTotal, respectivamente.
El mtodo abonar (lneas 43 a 46) agrega un monto de dinero (el parmetro monto) a una Cuenta
como parte de una transaccin de depsito. Este mtodo agrega el monto slo al atributo saldoTotal
(lnea 45). El dinero abonado a una cuenta durante un depsito no se vuelve disponible de inmediato,
por lo que slo modificamos el saldo total. Supondremos que el banco actualiza despus el saldo disponible de manera apropiada. Nuestra implementacin de la clase Cuenta slo incluye los mtodos
requeridos para realizar transacciones con el ATM. Por lo tanto, omitiremos los mtodos que invocara
cualquier otro sistema bancario para sumar al atributo saldoDisponible (confirmar un depsito) o restar
del atributo saldoTotal (rechazar un depsito).
El mtodo cargar (lneas 49 a 53) resta un monto de dinero (el parmetro monto) de una Cuenta,
como parte de una transaccin de retiro. Este mtodo resta el monto tanto del atributo saldoDisponible
(lnea 51) como del atributo saldoTotal (lnea 52), debido a que un retiro afecta ambas unidades del
saldo de una cuenta.
El mtodo obtenerNumeroCuenta (lneas 56 a 59) proporciona acceso al numeroCuenta de una
Cuenta. Incluimos este mtodo en nuestra implementacin de modo que un cliente de la clase (por
ejemplo, BaseDatosBanco) pueda identificar a una Cuenta especfica. Por ejemplo, BaseDatosBanco
contiene muchos objetos Cuenta, y puede invocar este mtodo en cada uno de sus objetos Cuenta para
localizar el que tenga cierto nmero de cuenta especfico.
// BaseDatosBanco.java
3
4
7
8
public BaseDatosBanco()
10
Fig. 13.19 La clase BaseDatosBanco representa a la base de datos de informacin sobre las cuentas del banco
(parte 1 de 3).
13.4
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
535
Fig. 13.19 La clase BaseDatosBanco representa a la base de datos de informacin sobre las cuentas del banco
(parte 2 de 3).
536
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
62
63
64
65
66
67
Fig. 13.19 La clase BaseDatosBanco representa a la base de datos de informacin sobre las cuentas del banco
(parte 3 de 3).
Determinamos un atributo de tipo referencia para la clase BaseDatosBanco con base en su relacin de composicin con la clase Cuenta. En la figura 13.9 vimos que una BaseDatosBanco est
compuesta de cero o ms objetos de la clase Cuenta. La lnea 6 implementa el atributo cuentas
(un arreglo de objetos Cuenta) para implementar esta relacin de composicin. La clase BaseDatosBanco tiene un constructor sin argumentos (lneas 9 a 14) que inicializa cuentas para que contenga
un conjunto de nuevos objetos Cuenta. A fin de probar el sistema, declaramos cuentas de modo
que contenga slo dos elementos en el arreglo (lnea 11), que instanciamos como nuevos objetos
Cuenta con datos de prueba (lneas 12 y 13). El constructor de Cuenta tiene cuatro parmetros:
el nmero de cuenta, el NIP asignado a la cuenta, el saldo disponible inicial y el saldo total inicial.
Recuerde que la clase BaseDatosBanco sirve como intermediario entre la clase ATM y los mismos objetos Cuenta que contienen la informacin sobre la cuenta de un usuario. Por ende, los mtodos de
la clase BaseDatosBanco no hacen ms que invocar a los mtodos correspondientes del objeto Cuenta
que pertenece al usuario actual del ATM.
Incluimos el mtodo private utilitario obtenerCuenta (lneas 17 a 28) para permitir que la
BaseDatosBanco obtenga una referencia a una Cuenta especfica dentro del arreglo cuentas. Para localizar la Cuenta del usuario, la BaseDatosBanco compara el valor devuelto por el mtodo obtenerNumeroCuenta para cada elemento de cuentas con un nmero de cuenta especfico, hasta encontrar una
coincidencia. Las lneas 20 a 25 recorren el arreglo cuentas. Si el nmero de cuenta de cuentaActual
es igual al valor del parmetro numeroCuenta, el mtodo devuelve de inmediato la cuentaActual.
Si ninguna cuenta tiene el nmero de cuenta dado, entonces la lnea 27 devuelve null.
El mtodo autenticarUsuario (lneas 32 a 42) aprueba o desaprueba la identidad de un usuario
del ATM. Este mtodo recibe un nmero de cuenta y un NIP especificados por el usuario como argumentos, e indica si coinciden con el nmero de cuenta y NIP de una Cuenta en la base de datos.
La lnea 35 llama al mtodo obtenerCuenta, el cual devuelve una Cuenta con numeroCuentaUsuario
como su nmero de cuenta, o null para indicar que el numeroCuentaUsuario es invlido. Si obtenerCuenta devuelve un objeto Cuenta, la lnea 39 regresa el valor boolean devuelto por el mtodo
validarNIP de ese objeto. El mtodo autenticarUsuario de BaseDatosBanco no realiza la comparacin de NIP por s solo, sino que enva nipUsuario al mtodo validarNIP del objeto Cuenta para
que lo haga. El valor devuelto por el mtodo validarNIP de Cuenta indica si el NIP especificado por
el usuario coincide con el NIP de la Cuenta del usuario, por lo que el mtodo autenticarUsuario
simplemente devuelve este valor al cliente de la clase (es decir, el ATM).
BaseDatosBanco confa en que el ATM invoque al mtodo autenticarUsuario y reciba un valor
de retorno true antes de permitir que el usuario realice transacciones. BaseDatosBanco tambin
confa que cada objeto Transaccion creado por el ATM contendr el nmero de cuenta vlido del
usuario actual autenticado, y que ste ser el nmero de cuenta que se pase al resto de los mtodos
de BaseDatosBanco como el argumento numeroCuentaUsuario. Por lo tanto, los mtodos obtenerSaldoDisponible (lneas 45 a 48), obtenerSaldoTotal (lneas 51 a 54), abonar (lneas 57 a 60) y
cargar (lneas 63 a 66) tan slo obtienen el objeto Cuenta del usuario con el mtodo utilitario obte-
13.4
537
nerCuenta,
y despus invocan al mtodo de Cuenta apropiado con base en ese objeto. Sabemos que
las llamadas a obtenerCuenta desde estos mtodos nunca devolvern null, puesto que numeroCuentaUsuario se debe referir a una Cuenta existente. Los mtodos obtenerSaldoDisponible
y obtenerSaldoTotal devuelven los valores que regresan los correspondientes mtodos de Cuenta.
Adems, abonar y cargar simplemente redirigen el parmetro monto a los mtodos de Cuenta que
invocan.
// Transaccion.java
3
4
9
10
11
12
13
14
numeroCuenta = numeroCuentaUsuario;
15
pantalla = pantallaATM;
baseDatosBanco = baseDatosBancoATM;
16
17
18
19
20
21
{
return numeroCuenta;
22
23
24
25
26
27
28
29
return pantalla;
} // fin del mtodo obtenerPantalla
30
Fig. 13.20 La superclase abstracta Transaccion representa una transaccin con el ATM (parte 1 de 2).
538
31
32
33
34
35
36
37
38
39
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
// devuelve una referencia a la base de datos del banco
public BaseDatosBanco obtenerBaseDatosBanco()
{
return baseDatosBanco;
} // fin del mtodo obtenerBaseDatosBanco
// realiza la transaccin (cada subclase sobrescribe este mtodo)
abstract public void ejecutar();
} // fin de la clase Transaccion
Fig. 13.20 La superclase abstracta Transaccion representa una transaccin con el ATM (parte 2 de 2).
La clase Transaccion tiene un constructor (lneas 11 a 17) que recibe como argumentos el nmero
de cuenta del usuario actual y referencias tanto a la pantalla del ATM como a la base de datos del banco.
Puesto que Transaccion es una clase abstracta, este constructor se llama slo a travs de los constructores
de las subclases de Transaccion.
La clase tiene tres mtodos obtener pblicos: obtenerNumeroCuenta (lneas 20 a 23), obtenerPantalla (lneas 26 a 29) y obtenerBaseDatosBanco (lneas 32 a 35). Estos mtodos son heredados
por las subclases de Transaccion y se utilizan para obtener acceso a los atributos private de esta clase.
La clase Transaccion tambin declara el mtodo abstract ejecutar (lnea 38). No tiene caso
proveer la implementacin de este mtodo, ya que una transaccin genrica no se puede ejecutar.
Por ende, declaramos este mtodo como abstract y forzamos a cada subclase de Transaccion a proveer una implementacin concreta que ejecute este tipo especfico de transaccin.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SolicitudSaldo.java
// Representa una transaccin de solicitud de saldo en el ATM
public class SolicitudSaldo extends Transaccion
{
// constructor de SolicitudSaldo
public SolicitudSaldo( int numeroCuentaUsuario, Pantalla pantallaATM,
BaseDatosBanco baseDatosBanco )
{
super( numeroCuentaUsuario, pantallaATM, baseDatosBanco );
} // fin del constructor de SolicitudSaldo
// realiza la transaccin
@Override
public void ejecutar()
{
Fig. 13.21 La clase SolicitudSaldo representa a una transaccin de solicitud de saldo en el ATM (parte 1 de 2).
13.4
17
18
19
539
20
21
22
double saldoDisponible =
23
baseDatosBanco.obtenerSaldoDisponible( obtenerNumeroCuenta() );
24
25
26
double saldoTotal =
27
baseDatosBanco.obtenerSaldoTotal( obtenerNumeroCuenta() );
28
29
30
31
32
pantalla.mostrarMontoDolares( saldoDisponible );
33
34
pantalla.mostrarMontoDolares( saldoTotal );
35
pantalla.mostrarLineaMensaje( );
36
37
);
Fig. 13.21 La clase SolicitudSaldo representa a una transaccin de solicitud de saldo en el ATM (parte 2 de 2).
La clase SolicitudSaldo sobrescribe el mtodo abstracto ejecutar de Transaccin para proveer una implementacin discreta (lneas 14 a 36) que realiza los pasos involucrados en una solicitud
de saldo. Las lneas 18 a 19 obtienen referencias a la base de datos del banco y la pantalla del ATM,
al invocar a los mtodos heredados de la superclase Transaccion. Las lneas 22 y 23 obtienen el saldo
disponible de la cuenta implicada, mediante una invocacin al mtodo obtenerSaldoDisponible
de baseDatosBanco. La lnea 23 usa el mtodo heredado obtenerNumeroCuenta para obtener el nmero de cuenta del usuario actual, que despus pasa a obtenerSaldoDisponible. Las lneas 26 y 27
obtienen el saldo total de la cuenta del usuario actual. Las lneas 30 a 35 muestran la informacin del
saldo en la pantalla del ATM. Recuerde que mostrarMontoDolares recibe un argumento double y
lo imprime en la pantalla, con formato de monto en dlares. Por ejemplo, si el saldoDisponible de
un usuario es 1000.5, la lnea 32 imprime $1,000.50. La lnea 35 inserta una lnea en blanco
de salida para separar la informacin del saldo de la salida subsiguiente (es decir, el men principal
repetido por la clase ATM despus de ejecutar la SolicitudSaldo).
540
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
// Retiro.java
// Representa una transaccin de retiro en el ATM
public class Retiro extends Transaccion
{
private int monto; // monto a retirar
private Teclado teclado; // referencia al teclado
private DispensadorEfectivo dispensadorEfectivo; // referencia al dispensador de
efectivo
// constante que corresponde a la opcin del men a cancelar
private final static int CANCELO = 6;
// constructor de Retiro
public Retiro( int numeroCuentaUsuario, Pantalla pantallaATM,
BaseDatosBanco baseDatosBancoATM, Teclado tecladoATM,
DispensadorEfectivo dispensadorEfectivoATM )
{
// inicializa las variables de la superclase
super( numeroCuentaUsuario, pantallaATM, baseDatosBancoATM );
// inicializa las referencias al teclado y al dispensador de efectivo
teclado = tecladoATM;
dispensadorEfectivo = dispensadorEfectivoATM;
} // fin del constructor de Retiro
// realiza la transaccin
@Override
public void ejecutar()
{
boolean efectivoDispensado = false; // no se ha dispensado an el efectivo
double saldoDisponible; // monto disponible para retirar
// obtiene referencias a la base de datos del banco y la pantalla
BaseDatosBanco baseDatosBanco = obtenerBaseDatosBanco();
Pantalla pantalla = obtenerPantalla();
// itera hasta que se dispense el efectivo o que cancele el usuario
do
{
// obtiene un monto de retiro elegido por el usuario
monto = mostrarMenuDeMontos();
// comprueba si el usuario eligi un monto de retiro o si cancel
if ( monto != CANCELO )
{
// obtiene el saldo disponible de la cuenta implicada
saldoDisponible =
baseDatosBanco.obtenerSaldoDisponible( obtenerNumeroCuenta() );
// comprueba si el usuario tiene suficiente dinero en la cuenta
if ( monto <= saldoDisponible )
{
Fig. 13.22 La clase Retiro representa una transaccin de retiro en el ATM (parte 1 de 3).
13.4
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
541
Fig. 13.22 La clase Retiro representa una transaccin de retiro en el ATM (parte 2 de 3).
542
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
pantalla.mostrarLineaMensaje( 4 - $100 );
pantalla.mostrarLineaMensaje( 5 - $200 );
pantalla.mostrarLineaMensaje( 6 - Cancelar transaccion );
pantalla.mostrarMensaje( \nSeleccione un monto a retirar: );
int entrada = teclado.obtenerEntrada(); // obtiene la entrada del usuario
mediante el teclado
// determina cmo proceder con base en el valor de la entrada
switch ( entrada )
{
case 1: // si el usuario eligi un monto de retiro
case 2: // (es decir, si eligi la opcin 1, 2, 3, 4 o 5), devolver
case 3: // el monto correspondiente del arreglo montos
case 4:
case 5:
opcionUsuario = montos[ entrada ]; // guarda la eleccin del usuario
break;
case CANCELO: // el usuario eligi cancelar
opcionUsuario = CANCELO; // guarda la eleccin del usuario
break;
default: // el usuario no introdujo un valor del 1 al 6
pantalla.mostrarLineaMensaje(
\nSeleccion invalida. Intente de nuevo. );
} // fin de switch
} // fin de while
return opcionUsuario; // devuelve el monto de retiro o CANCELO
} // fin del mtodo mostrarMenuDeMontos
} // fin de la clase Retiro
Fig. 13.22 La clase Retiro representa una transaccin de retiro en el ATM (parte 3 de 3).
El constructor de la clase Retiro (lneas 14 a 24) tiene cinco parmetros. Usa super para pasar los
parmetros numeroCuentaUsuario, pantallaATM y baseDatosBancoATM al constructor de la superclase
Transaccion para establecer los atributos que Retiro hereda de Transaccion. El constructor tambin
recibe las referencias tecladoATM y dispensadorEfectivoATM como parmetros, y las asigna a los atributos de tipo referencia teclado y dispensadorEfectivo.
La clase Retiro sobrescribe el mtodo ejecutar de Transaccion con una implementacin concreta
(lneas 27 a 85) que realiza los pasos de un retiro. La lnea 30 declara e inicializa una variable boolean
local llamada efectivoDispensado, la cual indica si se dispens efectivo (es decir, si la transaccin se
complet con xito), y en un principio es false. La lnea 31 declara la variable double local llamada
saldoDisponible, la cual almacenar el saldo disponible del usuario durante una transaccin de retiro.
Las lneas 34 y 35 obtienen referencias a la base de datos del banco y a la pantalla del ATM, invocando los
mtodos heredados de la superclase Transaccion.
Las lneas 38 a 83 contienen un ciclo dowhile que ejecuta su cuerpo hasta dispensar efectivo (es
decir, hasta que efectivoDispensado se vuelva true) o hasta que el usuario elija cancelar (en cuyo caso,
el ciclo termina). Usamos este ciclo para regresar en forma continua al usuario al inicio de la transaccin
en caso de que ocurra un error (por ejemplo, si el monto de retiro solicitado es mayor que el saldo disponible del usuario, o mayor que la cantidad de efectivo en el dispensador). La lnea 41 muestra un men
de montos de retiro y obtiene una seleccin del usuario mediante una llamada al mtodo private utilitario
mostarMenuDeMontos (declarado en las lneas 89 a 133). Este mtodo muestra el men de montos y de-
13.4
543
vuelve un monto de retiro int, o la constante int CANCELO para indicar que el usuario opt por cancelar
la transaccin.
El mtodo mostrarMenuDeMontos (lneas 89 a 133) declara primero la variable local opcionUsuario (que en un principio vale 0) para almacenar el valor que devolver el mtodo (lnea 91).
La lnea 93 obtiene una referencia a la pantalla mediante una llamada al mtodo obtenerPantalla
heredado de la superclase Transaccion. La lnea 96 declara un arreglo entero de montos de retiro
que corresponden a los montos mostrados en el men de retiro. Ignoramos el primer elemento en
el arreglo (ndice 0), debido a que el men no tiene opcin 0. La instruccin while en las lneas 99
a 130 se repite hasta que opcionUsuario recibe un valor distinto de 0. En breve veremos que esto
ocurre cuando el usuario realiza una seleccin vlida del men. Las lneas 102 a 109 muestran el men
de retiro en la pantalla y piden al usuario que introduzca una opcin. La lnea 111 obtiene el entero
entrada por medio del teclado. La instruccin switch en las lneas 114 a 129 determina cmo proceder con base en la entrada del usuario. Si ste selecciona un nmero entre 1 y 5, la lnea 121 establece opcionUsuario en el valor del elemento en montos, en el ndice entrada. Por ejemplo, si el
usuario introduce 3 para retirar $60, la lnea 121 establece opcionUsuario en el valor de montos[3]
(es decir, 60). La lnea 122 termina la instruccin switch. La variable opcionUsuario ya no es igual
a 0, por lo que la instruccin while en las lneas 99 a 130 termina y la lnea 132 devuelve opcionUsuario. Si el usuario selecciona la opcin del men para cancelar, se ejecutan las lneas 124 y 125,
las cuales establecen opcionUsuario en CANCELO y hacen que el mtodo devuelva este valor. Si el
usuario no introduce una seleccin vlida del men, las lneas 127 y 128 muestran un mensaje de
error y el usuario regresa al men retiro.
La lnea 44 en el mtodo ejecutar determina si el usuario seleccion un monto de retiro o
eligi cancelar. Si el usuario cancela, se ejecutan las lneas 80 y 81 para mostrar un mensaje apropiado
al usuario, antes de devolver el control al mtodo que hizo la llamada (el mtodo realizarTransacciones de ATM). Si el usuario selecciona un monto de retiro, las lneas 47 y 48 obtienen el saldo
disponible de la Cuenta del usuario actual y lo almacenan en la variable saldoDisponible. Luego,
la lnea 51 determina si el monto seleccionado es menor o igual que el saldo disponible del usuario.
Si no es as, las lneas 73 a 75 muestran un mensaje de error apropiado. Despus el control contina
hasta el final del ciclo dowhile, y ste se repite debido a que efectivoDispensado sigue siendo
false. Si el saldo del usuario es suficientemente alto, la instruccin if en la lnea 54 determina si el
dispensador de efectivo tiene dinero suficiente para cumplir con la solicitud de retiro, invocando
al mtodo haySuficienteEfectivoDisponible de dispensadorEfectivo. Si este mtodo devuelve
false, las lneas 67 a 69 muestran un mensaje de error apropiado y se repite el ciclo dowhile.
Si hay suficiente efectivo disponible, entonces se cumplen los requisitos para el retiro y la lnea 57
carga monto a la cuenta del usuario en la base de datos. Despus, las lneas 59 y 60 instruyen al dispensador de efectivo para que dispense el efectivo al usuario y establecen efectivoDispensado en
true. Por ltimo, las lneas 63 y 64 muestran un mensaje al usuario para indicarle que se dispens
el efectivo. Puesto que ahora efectivoDispensado es true, el control contina despus del ciclo
dowhile. No aparecen instrucciones adicionales debajo del ciclo, por lo que el mtodo regresa.
544
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
// Deposito.java
// Representa una transaccin de depsito en el ATM
public class Deposito extends Transaccion
{
private double monto; // monto a depositar
private Teclado teclado; // referencia al teclado
private RanuraDeposito ranuraDeposito; // referencia a la ranura de depsito
private final static int CANCELO = 0; // constante para la opcin de cancelar
// constructor de Deposito
public Deposito( int numeroCuentaUsuario, Pantalla pantallaATM,
BaseDatosBanco baseDatosBancoATM, Teclado tecladoATM,
RanuraDeposito ranuraDepositoATM )
{
// inicializa las variables de la superclase
super( numeroCuentaUsuario, pantallaATM, baseDatosBancoATM );
// inicializa las referencias al teclado y la ranura de depsito
teclado = tecladoATM;
ranuraDeposito = ranuraDepositoATM;
} // fin del constructor de Deposito
// realiza la transaccin
@Override
public void ejecutar()
{
BaseDatosBanco baseDatosBanco = obtenerBaseDatosBanco(); // obtiene la
referencia
Pantalla pantalla = obtenerPantalla(); // obtiene la referencia
monto = pedirMontoADepositar(); // obtiene el monto a depositar del usuario
// comprueba si el usuario introdujo un monto a depositar o cancel
if ( monto != CANCELO )
{
// solicita un sobre de depsito que contenga el monto especificado
pantalla.mostrarMensaje(
\nInserte un sobre que contenga );
pantalla.mostrarMontoDolares( monto );
pantalla.mostrarLineaMensaje( . );
// recibe el sobre de depsito
boolean seRecibioSobre = ranuraDeposito.seRecibioSobre();
// comprueba si se recibi el sobre de depsito
if ( seRecibioSobre )
{
pantalla.mostrarLineaMensaje( \nSe recibio su sobre de +
deposito.\nNOTA: El dinero que acaba de depositar no +
estara disponible sino hasta que verifiquemos el monto del +
efectivo y cualquier cheque incluido. );
Fig. 13.23 La clase Deposito representa una transaccin de depsito en el ATM (parte 1 de 2).
13.4
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
545
Fig. 13.23 La clase Deposito representa una transaccin de depsito en el ATM (parte 2 de 2).
Al igual que Retiro, la clase Deposito contiene un constructor (lneas 12 a 22) que pasa tres
parmetros al constructor de la superclase Transaccion. El constructor tambin tiene los parmetros
tecladoATM y ranuraDepositoATM, que asigna a los atributos correspondientes (lneas 20 y 21).
El mtodo ejecutar (lneas 25 a 66) sobrescribe la versin abstract en la superclase Transaccion
con una implementacin completa que realiza los pasos requeridos en una transaccin de depsito.
Las lneas 28 y 29 obtienen referencias a la base de datos y la pantalla. La lnea 31 pide al usuario que
introduzca un monto de depsito, para lo cual invoca al mtodo private utilitario pedirMontoADepositar (declarado en las lneas 69 a 85) y establece el atributo monto con el valor devuelto. El mtodo
pedirMontoADepositar pide al usuario que introduzca un monto de depsito como un nmero entero de centavos (debido a que el teclado del ATM no contiene un punto decimal; esto es consistente
con muchos ATM reales) y devuelve el valor double que representa el monto en dlares a depositar.
La lnea 71 en el mtodo pedirMontoADepositar obtiene una referencia a la pantalla del ATM.
Las lneas 74 y 75 muestran un mensaje que pide al usuario introducir un monto de depsito como un
nmero de centavos, o 0 para cancelar la transaccin. La lnea 76 obtiene la entrada del usuario desde
el teclado. Las lneas 79 a 84 determinan si el usuario introdujo un monto de depsito real o eligi
cancelar. Si opt por esto ltimo, la lnea 80 devuelve la constante CANCELO. De lo contrario, la lnea 83
546
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
devuelve el monto de depsito despus de convertirlo del nmero de centavos a un monto en dlares,
mediante la conversin de entrada a double, y despus lo divide entre 100. Por ejemplo, si un usuario
introduce 125 como el nmero de centavos, la lnea 83 devuelve el resultado de dividir 125.0 entre 100,
o 1.25; 125 centavos son $1.25.
Las lneas 34 a 65 en el mtodo ejecutar determinan si el usuario eligi cancelar la transaccin en
vez de introducir un monto de depsito. Si el usuario cancela, la lnea 64 muestra un mensaje apropiado y el mtodo regresa. Si el usuario introduce un monto de depsito, las lneas 37 a 40 instruyen
al usuario para que inserte un sobre de depsito con el monto correcto. Recuerde que el mtodo mostrarMontoDolares de Pantalla imprime un valor double con formato de monto en dlares.
La lnea 43 establece una variable boolean local en el valor devuelto por el mtodo seRecibioSobre
de ranuraDeposito, para indicar si se recibi un sobre de depsito. Recuerde que codificamos el mtodo
seRecibioSobre (lneas 8 a 11 de la figura 13.17) para que siempre devuelva true, debido a que estamos simulando la funcionalidad de la ranura de depsito y suponemos que el usuario siempre inserta un
sobre. Sin embargo, codificamos el mtodo ejecutar de la clase Deposito para que evale la posibilidad
de que el usuario no inserte un sobre; la buena ingeniera de software exige que los programas tomen
en cuenta todos los posibles valores de retorno. Por ende, la clase Deposito est preparada para futuras
versiones de seRecibioSobre que pudieran devolver false. Las lneas 48 a 54 se ejecutan si la ranura
de depsito recibe un sobre. Las lneas 48 a 51 muestran un mensaje apropiado al usuario. Despus, la
lnea 54 abona el monto de depsito a la cuenta del usuario en la base de datos. Las lneas 58 y 59 se ejecutarn si la ranura de depsito no recibe un sobre de depsito. En este caso, mostramos un mensaje
al usuario para indicarle que el ATM cancel la transaccin. A continuacin, el mtodo regresa sin modificar la cuenta del usuario.
// CasoEstudioATM.java
3
4
{
ATM elATM = new ATM();
elATM.run();
10
11
12
} // fin de main
} // fin de la clase CasoEstudioATM
Fig. 13.24
13.5 Conclusin
En este captulo us la herencia para optimizar el diseo del sistema de software del ATM, e implement por completo el ATM en Java. Felicidades por completar todo el caso de estudio del ATM!
547
Esperamos que haya encontrado esta experiencia valiosa y que refuerce muchos de los conceptos de
la programacin orientada a objetos que aprendi. En el siguiente captulo veremos las interfaces grficas de usuario (GUI) con ms detalle.
13.2
b.
13.3 El diseo para la clase Teclado produce el cdigo de la figura 13.25. Recuerde que la clase Teclado no tiene atributos en estos momentos, pero pueden volverse aparentes a medida que continuemos con la implementacin. Adems,
si furamos a disear un ATM real, el mtodo obtenerEntrada tendra que interactuar con el hardware del teclado del
ATM. En realidad recibiremos la entrada del teclado de una computadora personal, cuando escribamos el cdigo de Java
completo en la seccin 13.4.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Fig. 13.25 Cdigo de Java para la clase Teclado, con base en las figuras 13.1 y 13.2.
13.4
b.
13.5
Falso. UML requiere que se escriban los nombres de las clases abstractas y de los mtodos abstractos en cursiva.
13.6 El diseo para la clase Transaccion produce el cdigo de la figura 13.26. Los cuerpos del constructor de la clase y
los mtodos se completarn en la seccin 13.4. Cuando estn implementados por completo, los mtodos obtenerPantalla
y obtenerBaseDatosBanco devolvern los atributos de referencias private de la superclase Transaccion, llamados pantalla
y baseDatosBanco, respectivamente. Estos mtodos permiten que las subclases de Transaccion accedan a la pantalla del
ATM e interacten con la base de datos del banco.
1
2
3
4
5
6
7
Fig. 13.26 Cdigo de Java para la clase Transaccion, con base en las figuras 13.9 y 13.10 (parte 1 de 2).
548
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
Fig. 13.26 Cdigo de Java para la clase Transaccion, con base en las figuras 13.9 y 13.10 (parte 2 de 2).