Sunteți pe pagina 1din 39

13

No se puede trabajar
en lo abstracto.
I. M. Pei

Generalizar significa pensar.


Georg Wilhelm Friedrich Hegel

Todos somos un regalo,


sa es nuestra herencia.
Ethel Waters

Djenme caminar por los


campos de papel tocando
con mi varita mgica los
tallos secos y las mariposas
atrofiadas
Denise Levertov

Objetivos
En este captulo aprender a:

Incorporar la herencia en el
diseo del ATM.

Incorporar el polimorfismo
en el diseo del ATM.

Implementar por completo


en Java el diseo orientado
a objetos, basado en UML,
del software del ATM.

Estudiar un recorrido de
cdigo detallado del sistema
de software del ATM que
explica las cuestiones
de implementacin.

Caso de estudio del ATM,


Parte 2: Implementacin de
un diseo orientado a objetos

13.2

Inicio de la programacin de las clases del sistema ATM

13.1

Introduccin

13.2

Inicio de la programacin de las clases


del sistema ATM

13.3

Incorporacin de la herencia y el
polimorfismo en el sistema ATM

13.4

Implementacin del caso de estudio del ATM


13.4.1 La clase ATM
13.4.2 La clase Pantalla
13.4.3 La clase Teclado

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

Respuestas a los ejercicios de autoevaluacin

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.

13.2 Inicio de la programacin de las clases del sistema ATM


[Nota: esta seccin se puede ensear despus del captulo 8].

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

cuenta : Integer = 500


+ autenticarUsuario() : Boolean
+ obtenerSaldoDisponible() : Double
+ obtenerSaldoTotal() : Double
+ abonar()
+ cargar()

+ dispensarEfectivo()
+ haySuficienteEfectivoDisponible() : Boolean

RanuraDeposito
+ seRecibioSobreDeposito : Boolean

Fig. 13.1 Diagrama de clases con marcadores de visibilidad.

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

Inicio de la programacin de las clases del sistema ATM

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

Accede a/modifica un saldo


de cuenta a travs de

1
Contiene
0..*
Cuenta

Fig. 13.2 Diagrama de clases con flechas de navegabilidad.

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].

Implementacin del sistema ATM a partir de su diseo de UML


Ahora estamos listos para empezar a implementar el sistema ATM. Primero convertiremos las clases
de los diagramas de las figuras 13.1 y 13.2 en cdigo de Java. Este cdigo representar el esqueleto del
sistema. En la seccin 13.3 modificaremos el cdigo para incorporar el concepto orientado a objetos
de la herencia. En la seccin 13.4 presentaremos el cdigo de Java completo y funcional para nuestro
modelo.
Como ejemplo, empezaremos a desarrollar el cdigo a partir de nuestro diseo de la clase Retiro
en la figura 13.1. Utilizaremos esta figura para determinar los atributos y operaciones de la clase. Usaremos el modelo de UML en la figura 13.2 para determinar las asociaciones entre las clases. Seguiremos
estos cuatro lineamientos para cada clase:
1. Use el nombre que se localiza en el primer compartimiento para declarar la clase como public,
con un constructor sin parmetros vaco. Incluimos este constructor tan slo como un receptculo para recordarnos que la mayora de las clases necesitarn en definitiva constructores. En la
seccin 13.4, en donde completamos una versin funcional de esta clase, agregaremos todos
los argumentos y el cdigo necesarios al cuerpo del constructor. Por ejemplo, la clase Retiro

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.

// La clase Retiro representa una transaccin de retiro del ATM

public class Retiro

// constructor sin argumentos

public Retiro()

{
} // fin del constructor de Retiro sin argumentos

7
8

} // fin de la clase Retiro

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

// La clase Retiro representa una transaccin de retiro del ATM

public class Retiro

// atributos

private int numeroCuenta; // cuenta de la que se van a retirar los fondos

private double monto; // monto que se va a retirar de la cuenta

7
8

// constructor sin argumentos

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.

Ejercicios de autoevaluacin de la seccin 13.2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

515

// La clase Retiro representa una transaccin de retiro del ATM


public class Retiro
{
// atributos
private int numeroCuenta; // cuenta de la que se retirarn los fondos
private double monto; // monto a retirar
// referencias a los objetos asociados
private Pantalla pantalla; // pantalla del ATM
private Teclado teclado; // teclado del ATM
private DispensadorEfectivo dispensadorEfectivo; // dispensador de efectivo del ATM
private BaseDatosBanco baseDatosBanco; // base de datos de informacin de las cuentas
// constructor sin argumentos
public Retiro()
{
} // fin del constructor de Retiro sin argumentos
} // fin de la clase Retiro

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

// La clase Retiro representa una transaccin de retiro del ATM


public class Retiro
{
// atributos
private int numeroCuenta; // cuenta de la que se van a retirar los fondos
private double monto; // monto a retirar
// referencias a los objetos asociados
private Pantalla pantalla; // pantalla del ATM
private Teclado teclado; // teclado del ATM
private DispensadorEfectivo dispensadorEfectivo; // dispensador de efectivo del ATM
private BaseDatosBanco baseDatosBanco; // base de datos de informacin de las
cuentas
// constructor sin argumentos
public Retiro()
{
} // fin del constructor de Retiro sin argumentos
// operaciones
public void ejecutar()
{
} // fin del mtodo ejecutar
} // fin de la clase Retiro

Fig. 13.6 Cdigo de Java para la clase Retiro, con base en las figuras 13.1 y 13.2.

Ejercicios de autoevaluacin de la seccin 13.2


13.1 Indique si el siguiente enunciado es verdadero o falso, y si es falso, explique por qu: si un atributo de una clase
se marca con un signo menos () en un diagrama de clases, el atributo no es directamente accesible fuera de la clase.

516

Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos

13.2

En la figura 13.2, la asociacin entre los objetos ATM y Pantalla indica:


a) que podemos navegar de la Pantalla al ATM.
b) que podemos navegar del ATM a la Pantalla.
c) (a) y (b); la asociacin es bidireccional.
d) Ninguna de las anteriores.

13.3

Escriba cdigo de Java para empezar a implementar el diseo para la clase Teclado.

13.3 Incorporacin de la herencia y el polimorfismo en el


sistema ATM
[Nota: esta seccin se puede ensear despus del captulo 10].
Ahora regresaremos a nuestro diseo del sistema ATM para ver cmo podra beneficiarse de la herencia. Para aplicar la herencia, primero buscamos caractersticas comunes entre las clases del sistema.
Creamos una jerarqua de herencia para modelar las clases similares (pero no idnticas) de una forma
ms elegante y eficiente. Despus modificamos nuestro diagrama de clases para incorporar las nuevas
relaciones de herencia. Por ltimo, demostramos cmo traducir nuestro diseo actualizado en cdigo de Java.
En la seccin 12.3 nos topamos con el problema de representar una transaccin financiera en el
sistema. En vez de crear una clase para representar a todos los tipos de transacciones, optamos por crear
tres clases distintas de transacciones (SolicitudSaldo, Retiro y Deposito) para representar las transacciones que puede realizar el sistema ATM. La figura 13.7 muestra los atributos y operaciones de las
clases SolicitudSaldo, Retiro y Deposito. Estas clases tienen un atributo (numeroCuenta) y una operacin (ejecutar) en comn. Cada clase requiere que el atributo numeroCuenta especifique la cuenta
a la que se aplica la transaccin. Cada clase contiene la operacin ejecutar, que el ATM invoca para
realizar la transaccin. Es evidente que SolicitudSaldo, Retiro y Deposito representan tipos de transacciones. La figura 13.7 revela las caractersticas comunes entre las clases de transacciones, por lo que
el uso de la herencia para factorizar las caractersticas comunes parece apropiado para disear estas clases. Colocamos la funcionalidad comn en una superclase, Transaccion, que las clases SolicitudSaldo,
Retiro y Deposito extienden.

SolicitudSaldo
- numeroCuenta : Integer
+ ejecutar()
Retiro

Deposito

- numeroCuenta : Integer
- monto : Double

- numeroCuenta : Integer
- monto : Double

+ ejecutar()

+ ejecutar()

Fig. 13.7 Atributos y operaciones de las clases SolicitudSaldo, Retiro y Deposito.

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

13.3 Incorporacin de la herencia y el polimorfismo en el sistema ATM

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.

Procesamiento de objetos Transaccion mediante el polimorfismo


El polimorfismo proporciona al ATM una manera elegante de ejecutar todas las transacciones en general.
Por ejemplo, suponga que un usuario elige realizar una solicitud de saldo. El ATM establece una referencia Transaccion a un nuevo objeto de la clase SolicitudSaldo. Cuando el ATM utiliza su referencia

518

Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos
Transaccion para
SolicitudSaldo.

invocar el mtodo

ejecutar,

se hace una llamada a la versin de

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.

Atributo adicional de las clases Retiro y Deposito


Las subclases SolicitudSaldo, Retiro y Deposito heredan el atributo numeroCuenta de la superclase Transaccion, pero las clases Retiro y Deposito contienen el atributo adicional monto que las
diferencia de la clase SolicitudSaldo. Las clases Retiro y Deposito requieren este atributo adicional
para almacenar el monto de dinero que el usuario desea retirar o depositar. La clase SolicitudSaldo
no necesita dicho atributo, puesto que slo requiere un nmero de cuenta para ejecutarse. Aun cuando
dos de las tres subclases de Transaccion comparten el atributo monto, no lo colocamos en la superclase Transaccion; en la superclase slo colocamos las caractersticas comunes para todas las subclases, ya que de otra forma las subclases podran heredar atributos (y mtodos) que no necesitan y no
deben tener.

Diagrama de clases en el que se incorpora la jerarqua de Transaccion


La figura 13.9 presenta un diagrama de clases actualizado de nuestro modelo, en el cual se incorpora la
herencia y se introduce la clase Transaccion. Modelamos una asociacin entre la clase ATM y la clase
Transaccion para mostrar que la clase ATM, en cualquier momento dado, est ejecutando una transaccin o no lo est (es decir, existen cero o un objetos de tipo Transaccion en el sistema, en un momento
dado). Como un Retiro es un tipo de Transaccion, ya no dibujamos una lnea de asociacin directamente entre la clase ATM y la clase Retiro. La subclase Retiro hereda la asociacin de la superclase
Transaccion con la clase ATM. Las subclases SolicitudSaldo y Deposito tambin heredan esta asociacin, por lo que ya no existen las asociaciones entre la clase ATM y las clases SolicitudSaldo y Deposito,
que se haban omitido anteriormente.

13.3 Incorporacin de la herencia y el polimorfismo en el sistema ATM

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

Accede a/modifica el saldo


de una cuenta a travs de

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.

Observacin de ingeniera de software 13.1


Un diagrama de clases completo muestra todas las asociaciones entre clases, junto con
todos los atributos y operaciones para cada clase. Cuando el nmero de atributos, mtodos y asociaciones de las clases es substancial (como en las figuras 13.9 y 13.10),
una buena prctica que promueve la legibilidad es dividir esta informacin entre dos
diagramas de clases: uno que se enfoque en las asociaciones y el otro en los atributos y
mtodos.

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.

13.3 Incorporacin de la herencia y el polimorfismo en el sistema ATM

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

// La clase Retiro representa una transaccin de retiro en el ATM

public class Retiro extends Transaccion

} // fin de la clase Retiro

Fig. 13.11 Cdigo de Java para la estructura de la clase Retiro.


2. Si la clase A es una clase abstracta y la clase B es una subclase de la clase A, entonces la clase B
debe implementar los mtodos abstractos de la clase A, si la clase B va a ser una clase concreta.
Por ejemplo, la clase Transaccion contiene el mtodo abstracto ejecutar, por lo que la clase
Retiro debe implementar este mtodo si queremos crear una instancia de un objeto Retiro.
La figura 13.12 es el cdigo en Java para la clase Retiro de las figuras 13.9 y 13.10. La clase
Retiro hereda el campo numeroCuenta de la superclase Transaccion, por lo que Retiro no
necesita declarar este campo. La clase Retiro tambin hereda referencias a las clases Pantalla
y BaseDatosBanco de su superclase Transaccion, por lo que no incluimos estas referencias
en nuestro cdigo. La figura 13.10 especifica el atributo monto y la operacin ejecutar para
la clase Retiro. La lnea 6 de la figura 13.12 declara un campo para el atributo monto. Las
lneas 16 a 19 declaran la estructura de un mtodo para la operacin ejecutar. Recuerde
que la subclase Retiro debe proporcionar una implementacin concreta del mtodo abstract ejecutar de la superclase Transaccion. Las referencias teclado y dispensadorEfectivo (lneas 7 y 8) son campos derivados de las asociaciones de Retiro en la figura 13.9.
El constructor en la versin funcional completa de esta clase inicializar estas referencias con
objetos reales.
1

// Retiro.java

// Se gener usando los diagramas de clases en las figuras 13.9 y 13.10

public class Retiro extends Transaccion

// atributos

private double monto; // monto a retirar

private Teclado teclado; // referencia al teclado

private DispensadorEfectivo dispensadorEfectivo; // referencia al dispensador de


efectivo

9
10

// constructor sin argumentos

11

public Retiro()

12

13

} // fin del constructor de Retiro sin argumentos

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

public void ejecutar()

18

19
20

} // fin del mtodo ejecutar


} // fin de la clase Retiro

Fig. 13.12 Cdigo de Java para la clase Retiro, basada en las figuras 13.9 y 13.10 (parte 2 de 2).

Observacin de ingeniera de software 13.2


Varias herramientas de modelado de UML convierten los diseos basados en UML en
cdigo de Java, y pueden agilizar el proceso de implementacin en forma considerable.
Para obtener ms informacin sobre estas herramientas, visite nuestro Centro de recursos
de UML en www.deitel.com/UML/.

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.

Ejercicios de autoevaluacin de la seccin 13.3


13.4

UML utiliza una flecha con una


a) punta con relleno slido
b) punta triangular sin relleno
c) punta hueca en forma de diamante
d) punta lineal

para indicar una relacin de generalizacin.

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 Implementacin del caso de estudio del ATM


Esta seccin contiene la implementacin funcional completa de 673 lneas del sistema ATM. Consideramos las clases en el orden en el que las identificamos en la seccin 12.3: ATM, Pantalla, Teclado,
DispensadorEfectivo, RanuraDeposito, Cuenta, BaseDatosBanco, Transaccion, SolicitudSaldo,
Retiro y Deposito.
Aplicamos los lineamientos que vimos en las secciones 13.2 y 13.3 para codificar estas clases, con
base en la manera en que las modelamos en los diagramas de clases UML de las figuras 13.9 y 13.10.
Para desarrollar los cuerpos de los mtodos de las clases, nos referimos a los diagramas de actividad presentados en la seccin 12.5 y los diagramas de comunicaciones y secuencia presentados en la seccin 12.7.
Nuestro diseo del ATM no especifica toda la lgica de programacin, por lo que tal vez no especifique todos los atributos y operaciones requeridos para completar la implementacin del ATM. sta es

13.4

Implementacin del caso de estudio del ATM

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.

13.4.1 La clase ATM


La clase ATM (figura 13.13) representa al ATM como un todo. Las lneas 6 a 12 implementan los atributos de la clase. Determinamos todos estos atributos (excepto uno) de los diagramas de clase de las figuras
13.9 y 13.10. En la figura 13.10 implementamos el atributo Boolean usuarioAutenticado de UML
como un atributo boolean en Java (lnea 6). En la lnea 7 se declara un atributo que no se incluye en
nuestro diseo UML: el atributo int numeroCuentaActual, que lleva el registro del nmero de cuenta
del usuario autenticado actual. Pronto veremos cmo es que la clase utiliza este atributo. En las lneas 8
a 12 se declaran atributos de tipo de referencia, correspondientes a las asociaciones de la clase ATM modeladas en el diagrama de clases de la figura 13.9. Estos atributos permiten al ATM acceder a sus partes
(es decir, su Pantalla, Teclado, DispensadorEfectivo y RanuraDeposito) e interactuar con la base
de datos de informacin de cuentas bancarias (es decir, un objeto BaseDatosBanco).

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

Fig. 13.13 La clase ATM representa al ATM (parte 1 de 4).

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;

Fig. 13.13 La clase ATM representa al ATM (parte 2 de 4).

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

Implementacin del caso de estudio del ATM

525

boolean usuarioSalio = false; // el usuario no ha elegido salir


// itera mientras que el usuario no haya elegido la opcin para salir del
sistema
while ( !usuarioSalio )
{
// muestra el men principal y obtiene la seleccin del usuario
int seleccionMenuPrincipal = mostrarMenuPrincipal();
// decide cmo proceder, con base en la opcin del men seleccionada por el
usuario
switch ( seleccionMenuPrincipal )
{
// el usuario eligi realizar uno de tres tipos de transacciones
case SOLICITUD_SALDO:
case RETIRO:
case DEPOSITO:
// inicializa como nuevo objeto del tipo elegido
transaccionActual =
crearTransaccion( seleccionMenuPrincipal );
transaccionActual.ejecutar(); // ejecuta la transaccin
break;
case SALIR: // el usuario eligi terminar la sesin
pantalla.mostrarLineaMensaje( "\nCerrando el sistema..." );
usuarioSalio = true; // esta sesin con el ATM debe terminar
break;
default: // el usuario no introdujo un entero de 1 a 4
pantalla.mostrarLineaMensaje(
"\nNo introdujo una seleccion valida. Intente de nuevo." );
break;
} // fin de switch
} // fin de while
} // fin del mtodo realizarTransacciones
// muestra el men principal y devuelve una seleccin de entrada
private int mostrarMenuPrincipal()
{
pantalla.mostrarLineaMensaje( \nMenu principal: );
pantalla.mostrarLineaMensaje( 1 - Ver mi saldo );
pantalla.mostrarLineaMensaje( 2 - Retirar efectivo );
pantalla.mostrarLineaMensaje( 3 - Depositar fondos );
pantalla.mostrarLineaMensaje( 4 - Salir\n );
pantalla.mostrarMensaje( Escriba una opcion: );
return teclado.obtenerEntrada(); // devuelve la opcion seleccionada por el
usuario
} // fin del mtodo mostrarMenuPrincipal
// devuelve un objeto de la subclase especificada de Transaccion
private Transaccion crearTransaccion( int tipo )
{
Transaccion temp = null; // variable temporal Transaccion

Fig. 13.13 La clase ATM representa al ATM (parte 3 de 4).

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

// determina qu tipo de Transaccion crear


switch ( tipo )
{
case SOLICITUD_SALDO: // crea una nueva transaccin SolicitudSaldo
temp = new SolicitudSaldo(
numeroCuentaActual, pantalla, baseDatosBanco );
break;
case RETIRO: // crea una nueva transaccin Retiro
temp = new Retiro( numeroCuentaActual, pantalla,
baseDatosBanco, teclado, dispensadorEfectivo );
break;

142
143
144
145
146
147
148
149
150

case DEPOSITO: // crea una nueva transaccin Deposito


temp = new Deposito( numeroCuentaActual, pantalla,
baseDatosBanco, teclado, ranuraDeposito );
break;
} // fin de switch
return temp; // devuelve el objeto recin creado
} // fin del mtodo crearTransaccion
} // fin de la clase ATM

Fig. 13.13 La clase ATM representa al ATM (parte 4 de 4).


Las lneas 15 a 18 declaran constantes enteras que corresponden a las cuatro opciones en el men
principal del ATM (es decir, solicitud de saldo, retiro, depsito y salir). Las lneas 21 a 30 declaran
el constructor, el cual inicializa los atributos de la clase. Cuando se crea un objeto ATM por primera
vez, no se autentica ningn usuario, por lo que la lnea 23 inicializa usuarioAutenticado a false.
De igual forma, la lnea 24 inicializa numeroCuentaActual a 0 debido a que todava no hay un usuario
actual. Las lneas 25 a 28 crean instancias de nuevos objetos para representar las partes del ATM.
Recuerde que la clase ATM tiene relaciones de composicin con las clases Pantalla, Teclado, DispensadorEfectivo y RanuraDeposito, por lo que la clase ATM es responsable de su creacin. La lnea 29
crea un nuevo objeto BaseDatosBanco. [Nota: si ste fuera un sistema ATM real, la clase ATM recibira
una referencia a un objeto base de datos existente creado por el banco. Sin embargo, en esta implementacin slo estamos simulando la base de datos del banco, por lo que ATM crea el objeto BaseDatosBanco con el que interacta].

El mtodo run de ATM


El diagrama de clases de la figura 13.10 no lista ninguna operacin para la clase ATM. Ahora vamos a implementar una operacin (es decir, un mtodo public) en la clase ATM que permite a un cliente externo
de la clase (en este caso, la clase CasoEstudioATM) indicar al ATM que se ejecute. El mtodo run de ATM
(lneas 33 a 50) usa un ciclo infinito (lneas 36 a 49) para dar la bienvenida repetidas veces a un usuario,
tratar de autenticarlo y, si la autenticacin tiene xito, permite al usuario realizar transacciones. Una vez
que un usuario autenticado realiza las transacciones deseadas y selecciona la opcin para salir, el ATM
se reinicia a s mismo, muestra un mensaje de despedida al usuario y reinicia el proceso. Aqu usamos
un ciclo infinito para simular el hecho de que un ATM parece ejecutarse en forma continua hasta que
el banco lo apaga (una accin que est ms all del control del usuario). Un usuario del ATM tiene la
opcin de salir del sistema, pero no la habilidad de apagar el ATM por completo.
Autenticacin de un usuario
En el ciclo infinito del mtodo run, las lneas 39 a 43 provocan que el ATM de la bienvenida al usuario
y trate de autenticarlo repetidas veces, siempre y cuando ste no haya sido autenticado antes (es decir,

13.4

Implementacin del caso de estudio del ATM

527

que !usarioAutenticado sea true). La lnea 41 invoca al mtodo mostrarLineaMensaje de la pantalla


del ATM para mostrar un mensaje de bienvenida. Al igual que el mtodo mostrarMensaje de Pantalla
diseado en el caso de estudio, el mtodo mostrarLineaMensaje (declarado en las lneas 13 a 16 de
la figura 13.14) muestra un mensaje al usuario, slo que este mtodo tambin produce una nueva
lnea despus del mensaje. Agregamos este mtodo durante la implementacin para dar a los clientes
de la clase Pantalla un mayor control sobre la disposicin de los mensajes visualizados. La lnea 42
invoca el mtodo utilitario private autenticarUsuario de la clase ATM (declarado en las lneas 53
a 72) para tratar de autenticar al usuario.
Nos referimos al documento de requerimientos para determinar los pasos necesarios para autenticar al usuario, antes de permitir que ocurran transacciones. La lnea 55 del mtodo autenticarUsuario invoca al mtodo mostrarMensaje de la pantalla, para pedir al usuario que introduzca un
nmero de cuenta. La lnea 56 invoca el mtodo obtenerEntrada del teclado para obtener la entrada
del usuario, y despus almacena el valor entero introducido por el usuario en una variable local llamada numero-Cuenta. A continuacin, el mtodo autenticarUsuario pide al usuario que introduzca
un NIP (lnea 57), y almacena el NIP introducido por el usuario en la variable local nip (lnea 58).
En seguida, las lneas 61 y 62 tratan de autenticar al usuario pasando el numeroCuenta y nip introducidos por el usuario al mtodo autenticarUsuario de la baseDatosBanco. La clase ATM establece
su atributo usuarioAutenticado al valor booleano devuelto por este mtodo; usuarioAutenticado
se vuelve true si la autenticacin tiene xito (es decir, si numeroCuenta y nip coinciden con los de
una Cuenta existente en baseDatosBanco), y permanece como false en caso contrario. Si usuarioAutenticado es true, la lnea 67 guarda el nmero de cuenta introducido por el usuario (es decir,
numeroCuenta) en el atributo numeroCuentaActual del ATM. Los otros mtodos de ATM usan esta
variable cada vez que una sesin del ATM requiere acceso al nmero de cuenta del usuario. Si
usuarioAutenticado es false, las lneas 70 y 71 usan el mtodo mostrarLineaMensaje de pantalla
para indicar que se introdujo un nmero de cuenta invlido y/o NIP, por lo que el usuario debe intentar de nuevo. Establecemos numeroCuentaActual slo despus de autenticar el nmero de cuenta del
usuario y el NIP asociado; si la base de datos no puede autenticar al usuario, numeroCuentaActual
permanece como 0.
Despus de que el mtodo run intenta autenticar al usuario (lnea 42), si usuarioAutenticado sigue siendo false, el ciclo while en las lneas 39 a 43 se ejecuta de nuevo. Si ahora usuarioAutenticado
es true, el ciclo termina y el control contina en la lnea 45, que llama al mtodo utilitario realizarTransacciones de la clase ATM.

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.

Creacin de una transaccin


El mtodo crearTransaccion (lneas 127 a 149) usa una instruccin switch (lneas 132 a 146) para
instanciar un nuevo objeto de la subclase Transaccion del tipo indicado por el parmetro tipo. Recuerde que el mtodo realizarTransacciones pasa la seleccionMenuPrincipal a este mtodo slo cuando
seleccionMenuPrincipal contiene un valor que corresponde a uno de los tres tipos de transaccin. Por
lo tanto, tipo es SOLICITUD_SALDO, RETIRO o DEPOSITO. Cada case en la instruccin switch crea una
instancia de un nuevo objeto llamando al constructor de la subclase apropiada de Transaccion. Cada
constructor tiene una lista de parmetros nicos, con base en los datos especficos requeridos para inicializar el objeto de la subclase. Un objeto SolicitudSaldo slo requiere el nmero de cuenta del usuario
actual y referencias tanto a la pantalla como a la baseDatosBanco del ATM. Adems de estos parmetros,
un objeto Retiro requiere referencias al teclado y dispensadorEfectivo del ATM, y un objeto Deposito
requiere referencias al teclado y la ranuraDeposito del ATM. En las secciones 13.4.8 a 13.4.11 analizaremos las clases de transacciones con ms detalle.
Salir del men principal y procesar selecciones invlidas
Despus de ejecutar una transaccin (lnea 100 en realizarTransacciones), usuarioSalio sigue
siendo false y se repiten las lneas 83 a 111, en donde el usuario regresa al men principal. No obstante, si un usuario selecciona la opcin del men principal para salir en vez de realizar una transaccin,
la lnea 104 establece usuarioSalio a true, lo cual provoca que la condicin del ciclo while (!usuarioSalio) se vuelva false. Este while es la instruccin final del mtodo realizarTransacciones, por
lo que el control regresa al mtodo run que hizo la llamada. Si el usuario introduce una seleccin de
men invlida (es decir, que no sea un entero del 1 al 4), las lneas 107 y 108 muestran un mensaje
de error apropiado, usuarioSalio sigue siendo false y el usuario regresa al men principal para intentar de nuevo.
Esperar al siguiente usuario del ATM
Cuando realizarTransacciones devuelve el control al mtodo run, el usuario ha elegido salir del
sistema, por lo que las lneas 46 y 47 reinician los atributos usuarioAutenticado y numeroCuentaActual
del ATM como preparacin para el siguiente usuario del ATM. La lnea 48 muestra un mensaje de despedida antes de que el ATM inicie de nuevo y d la bienvenida al nuevo usuario.

13.4.2 La clase Pantalla


La clase Pantalla (figura 13.14) representa la pantalla del ATM y encapsula todos los aspectos relacionados con el proceso de mostrar la salida al usuario. La clase Pantalla simula la pantalla de un
ATM real mediante un monitor de computadora y muestra los mensajes de texto mediante los m-

13.4

Implementacin del caso de estudio del ATM

529

todos estndar de salida a la consola System.out.print, System.out.println y System.out.printf.


En este caso de estudio diseamos la clase Pantalla de modo que tenga una operacin: mostrarMensaje.
Para una mayor flexibilidad al mostrar mensajes en la Pantalla, ahora declararemos tres mtodos:
mostrarMensaje, mostrarLineaMensaje y mostrarMontoDolares.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

// 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

Fig. 13.14 La clase Pantalla representa la pantalla del ATM.


El mtodo mostrarMensaje (lneas 7 a 10) recibe un argumento String y lo imprime en la consola.
El cursor permanece en la misma lnea, lo que hace a este mtodo apropiado para mostrar indicadores al
usuario. El mtodo mostrarLineaMensaje (lneas 13 a 16) hace lo mismo mediante System.out.
println, que imprime una nueva lnea para mover el cursor a la siguiente lnea. Por ltimo, el mtodo
mostrarMontoDolares (lneas 19 a 22) imprime un monto en dlares con un formato apropiado (por
ejemplo, $1,234.56). La lnea 21 utiliza a System.out.printf para imprimir un valor double al que
se le aplica un formato con comas para mejorar la legibilidad, junto con dos lugares decimales.

13.4.3 La clase Teclado


La clase Teclado (figura 13.15) representa el teclado del ATM y es responsable de recibir toda la entrada
del usuario. Recuerde que estamos simulando este hardware, por lo que usaremos el teclado de la computadora para simular el teclado del ATM. Usamos la clase Scanner para obtener la entrada de consola del
usuario. Un teclado de computadora contiene muchas teclas que no se encuentran en el teclado del ATM.
No obstante, vamos a suponer que el usuario slo presionar las teclas en el teclado de computadora que
aparezcan tambin en el teclado del ATM: las teclas enumeradas del 0 al 9, y la tecla Intro.
La lnea 3 de la clase Teclado importa la clase Scanner para usarla en la clase Teclado. La lnea 7
declara la variable Scanner entrada como una variable de instancia. La lnea 12 en el constructor crea un
nuevo objeto Scanner que lee la entrada del flujo de entrada estndar (System.in) y asigna la referencia del objeto a la variable entrada. El mtodo obtenerEntrada (lneas 16 a 19) invoca al mtodo nextInt
de Scanner (lnea 18) para devolver el siguiente entero introducido por el usuario. [Nota: el mtodo

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

Fig. 13.15 La clase Teclado representa al teclado del ATM.


nextInt puede lanzar una excepcin InputMismatchException si el usuario introduce una entrada que

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.

13.4.4 La clase DispensadorEfectivo


La clase DispensadorEfectivo (figura 13.16) representa el dispensador de efectivo del ATM. La lnea 7 declara la constante CUENTA_INICIAL, la cual indica la cuenta inicial de billetes en el dispensador
de efectivo cuando el ATM inicia su operacin (es decir, 500). La lnea 8 implementa el atributo
cuenta (modelado en la figura 13.10), que lleva la cuenta del nmero de billetes restantes en el
DispensadorEfectivo en cualquier momento. El constructor (lneas 11 a 14) establece cuenta en
la cuenta inicial. DispensadorEfectivo tiene 2 mtodos public: dispensarEfectivo (lneas 17 a 21)
y haySuficienteEfectivoDisponible (lneas 24 a 32). La clase confa en que un cliente (es decir,
Retiro) llamar a dispensarEfectivo slo despus de establecer que hay suficiente efectivo disponible mediante una llamada a haySuficienteEfectivoDisponible. Por ende, dispensarEfectivo
tan slo simula el proceso de dispensar la cantidad solicitada sin verificar si en realidad hay suficiente efectivo disponible.
1

// DispensadorEfectivo.java

// Representa al dispensador de efectivo del ATM

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

Implementacin del caso de estudio del ATM

531

public class DispensadorEfectivo


{
// el nmero inicial predeterminado de billetes en el dispensador de efectivo
private final static int CUENTA_INICIAL = 500;
private int cuenta; // nmero restante de billetes de $20
// el constructor sin argumentos de DispensadorEfectivo inicializa cuenta con el
valor predeterminado
public DispensadorEfectivo()
{
cuenta = CUENTA_INICIAL; // establece el atributo cuenta al valor predeterminado
} // fin del constructor de DispensadorEfectivo
// simula la accin de dispensar el monto especificado de efectivo
public void dispensarEfectivo( int monto )
{
int billetesRequeridos = monto / 20; // nmero de billetes de $20 requeridos
cuenta -= billetesRequeridos; // actualiza la cuenta de billetes
} // fin del mtodo dispensarEfectivo
// indica si el dispensador de efectivo puede dispensar el monto deseado
public boolean haySuficienteEfectivoDisponible( int monto )
{
int billetesRequeridos = monto / 20; // nmero de billetes de $20 requeridos
if ( cuenta >= billetesRequeridos )
return true; // hay suficientes billetes disponibles
else
return false; // no hay suficientes billetes disponibles
} // fin del mtodo haySuficienteEfectivoDisponible
} // fin de la clase DispensadorEfectivo

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,

13.4.5 La clase RanuraDeposito


La clase RanuraDeposito (figura 13.17) representa a la ranura de depsito del ATM. Al igual que la clase
DispensadorEfectivo, la clase RanuraDeposito tan slo simula la funcionalidad del hardware real de

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

// Representa a la ranura de depsito del ATM

con un mtodo: seRecibio-

3
4

public class RanuraDeposito

// indica si se recibi el sobre (siempre devuelve true, ya que sta

// es slo una simulacin de software de una ranura de depsito real)

public boolean seRecibioSobre()

{
return true; // se recibi el sobre

10

} // fin del mtodo seRecibioSobre

11
12

} // fin de la clase RanuraDeposito

Fig. 13.17 La clase RanuraDeposito representa a la ranura de depsito del ATM.

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.

13.4.6 La clase Cuenta


La clase Cuenta (figura 13.18) representa a una cuenta bancaria. Cada Cuenta tiene cuatro atributos
(modelados en la figura 13.10): numeroCuenta, nip, saldoDisponible y saldoTotal. Las lneas 6 a 9
implementan estos atributos como campos private. La variable saldoDisponible representa el monto
de fondos disponibles para retirar. La variable saldoTotal representa el monto de fondos disponibles,
junto con el monto de los fondos depositados pendientes de confirmacin o liberacin.

// Cuenta.java

// Representa a una cuenta bancaria

3
4

public class Cuenta

private int numeroCuenta; // nmero de cuenta

private int nip; // NIP para autenticacin

private double saldoDisponible; // fondos disponibles para retirar

private double saldoTotal; // fondos disponibles + depsitos pendientes

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

Implementacin del caso de estudio del ATM

533

// el constructor de Cuenta inicializa los atributos


public Cuenta( int elNumeroDeCuenta, int elNIP,
double elSaldoDisponible, double elSaldoTotal )
{
numeroCuenta = elNumeroDeCuenta;
nip = elNIP;
saldoDisponible = elSaldoDisponible;
saldoTotal = elSaldoTotal;
} // fin del constructor de Cuenta
// determina si un NIP especificado por el usuario coincide con el NIP en la Cuenta
public boolean validarNIP( int nipUsuario )
{
if ( nipUsuario == nip )
return true;
else
return false;
} // fin del mtodo validarNIP
// devuelve el saldo disponible
public double obtenerSaldoDisponible()
{
return saldoDisponible;
} // fin de obtenerSaldoDisponible
// devuelve el saldo total
public double obtenerSaldoTotal()
{
return saldoTotal;
} // fin del mtodo obtenerSaldoTotal
// abona un monto a la cuenta
public void abonar( double monto )
{
saldoTotal += monto; // lo suma al saldo total
} // fin del mtodo abonar
// carga un monto a la cuenta
public void cargar( double monto )
{
saldoDisponible -= monto; // lo resta del saldo disponible
saldoTotal -= monto; // lo resta del saldo total
} // fin del mtodo cargar
// devuelve el nmero de cuenta
public int obtenerNumeroCuenta()
{
return numeroCuenta;
} // fin del mtodo obtenerNumeroCuenta
} // fin de la clase Cuenta

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.

13.4.7 La clase BaseDatosBanco


La clase BaseDatosBanco (figura 13.19) modela la base de datos del banco con la que el ATM interacta para acceder a la informacin de la cuenta de un usuario y modificarla. En el captulo 28 estudiaremos el acceso a las bases de datos. Por ahora modelaremos la base de datos como un arreglo.
Un ejercicio en el captulo 28 le pedir que vuelva a implementar esta parte del ATM, usando una base
de datos real.

// BaseDatosBanco.java

// Representa a la base de datos de informacin de cuentas bancarias

3
4

public class BaseDatosBanco

private Cuenta cuentas[]; // arreglo de objetos Cuenta

7
8

// el constructor sin argumentos de BaseDatosBanco inicializa a cuentas

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

Implementacin del caso de estudio del ATM

535

cuentas = new Cuenta[ 2 ]; // slo 2 cuentas para probar


cuentas[ 0 ] = new Cuenta( 12345, 54321, 1000.0, 1200.0 );
cuentas[ 1 ] = new Cuenta( 98765, 56789, 200.0, 200.0 );
} // fin del constructor sin argumentos de BaseDatosBanco
// obtiene el objeto Cuenta que contiene el nmero de cuenta especificado
private Cuenta obtenerCuenta( int numeroCuenta )
{
// itera a travs de cuentas, buscando el nmero de cuenta que coincida
for ( Cuenta cuentaActual : cuentas )
{
// devuelve la cuenta actual si encuentra una coincidencia
if ( cuentaActual.obtenerNumeroCuenta() == numeroCuenta )
return cuentaActual;
} // fin de for
return null; // si no se encontr una cuenta que coincida, devuelve null
} // fin del mtodo obtenerCuenta
// determina si el nmero de cuenta y el NIP especificados por el usuario coinciden
// con los de una cuenta en la base de datos
public boolean autenticarUsuario( int numeroCuentaUsuario, int nipUsuario )
{
// trata de obtener la cuenta con el nmero de cuenta
Cuenta cuentaUsuario = obtenerCuenta( numeroCuentaUsuario );
// si la cuenta existe, devuelve el resultado del mtodo validarNIP de Cuenta
if ( cuentaUsuario != null )
return cuentaUsuario.validarNIP( nipUsuario );
else
return false; // no se encontr el nmero de cuenta, por lo que devuelve false
} // fin del mtodo autenticarUsuario
// devuelve el saldo disponible de la Cuenta con el nmero de cuenta especificado
public double obtenerSaldoDisponible( int numeroCuentaUsuario )
{
return obtenerCuenta( numeroCuentaUsuario ).obtenerSaldoDisponible();
} // fin del mtodo obtenerSaldoDisponible
// devuelve el saldo total de la Cuenta con el nmero de cuenta especificado
public double obtenerSaldoTotal( int numeroCuentaUsuario )
{
return obtenerCuenta( numeroCuentaUsuario ).obtenerSaldoTotal();
} // fin del mtodo obtenerSaldoTotal
// abona un monto a la Cuenta a travs del nmero de cuenta especificado
public void abonar( int numeroCuentaUsuario, double monto )
{
obtenerCuenta( numeroCuentaUsuario ).abonar( monto );
} // fin del mtodo abonar

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

// carga un monto a la Cuenta con el nmero de cuenta especificado

63

public void cargar( int numeroCuentaUsuario, double monto )

64

65
66
67

obtenerCuenta( numeroCuentaUsuario ).cargar( monto );


} // fin del mtodo cargar
} // fin de la clase BaseDatosBanco

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

Implementacin del caso de estudio del ATM

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.

13.4.8 La clase Transaccion


La clase Transaccion (figura 13.20) es una superclase abstracta que representa la nocin de una transaccin con el ATM. Contiene las caractersticas comunes de las subclases SolicitudSaldo, Retiro
y Deposito. Esta clase se expande a partir del cdigo estructural que se desarroll por primera vez
en la seccin 13.3. La lnea 4 declara esta clase como abstract. Las lneas 6 a 8 declaran los atributos private de las clases. En el diagrama de clases de la figura 13.10 vimos que la clase Transaccion
contiene un atributo llamado numeroCuenta (lnea 6), el cual indica la cuenta involucrada en la
Transaccion. Luego derivamos los atributos de Pantalla (lnea 7) y de BaseDatosBanco (lnea8) de
la clase Transaccion asociada y que se modela en la figura 13.9. Todas las transacciones requieren
acceso a la pantalla del ATM y a la base de datos del banco.
1

// Transaccion.java

// La superclase abstracta Transaccion representa una transaccin con el ATM

3
4

public abstract class Transaccion

private int numeroCuenta; // indica la cuenta implicada

private Pantalla pantalla; // pantalla del ATM

private BaseDatosBanco baseDatosBanco; // base de datos de informacin de cuentas

9
10

// el constructor de Transaccion es invocado por las subclases mediante super()

11

public Transaccion( int numeroCuentaUsuario, Pantalla pantallaATM,


BaseDatosBanco baseDatosBancoATM )

12
13

14

numeroCuenta = numeroCuentaUsuario;

15

pantalla = pantallaATM;
baseDatosBanco = baseDatosBancoATM;

16
17

} // fin del constructor de Transaccion

18
19

// devuelve el nmero de cuenta

20

public int obtenerNumeroCuenta()

21

{
return numeroCuenta;

22
23

} // fin del mtodo obtenerNumeroCuenta

24
25

// devuelve una referencia a la pantalla

26

public Pantalla obtenerPantalla()

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.

13.4.9 La clase SolicitudSaldo


La clase SolicitudSaldo (figura 13.21) extiende a Transaccion y representa una transaccin de solicitud de saldo con el ATM. SolicitudSaldo no tiene atributos propios, pero hereda los atributos numeroCuenta, pantalla y baseDatosBanco de Transaccion, a los cuales se puede acceder por medio de los
mtodos public obtener de Transaccion. El constructor de SolicitudSaldo recibe los argumentos
correspondientes a estos atributos, y lo nico que hace es reenviarlos al constructor de Transaccion
mediante el uso de super (lnea 10).

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

Implementacin del caso de estudio del ATM

17

// obtiene referencias a la base de datos del banco y la pantalla

18

BaseDatosBanco baseDatosBanco = obtenerBaseDatosBanco();

19

Pantalla pantalla = obtenerPantalla();

539

20
21

// obtiene el saldo disponible para la cuenta implicada

22

double saldoDisponible =

23

baseDatosBanco.obtenerSaldoDisponible( obtenerNumeroCuenta() );

24
25

// obtiene el saldo total para la cuenta implicada

26

double saldoTotal =

27

baseDatosBanco.obtenerSaldoTotal( obtenerNumeroCuenta() );

28
29

// muestra la informacin del saldo en la pantalla

30

pantalla.mostrarLineaMensaje( \nInformacion de saldo: );

31

pantalla.mostrarMensaje( - Saldo disponible: );

32

pantalla.mostrarMontoDolares( saldoDisponible );

33

pantalla.mostrarMensaje( \n - Saldo total:

34

pantalla.mostrarMontoDolares( saldoTotal );

35

pantalla.mostrarLineaMensaje( );

36
37

);

} // fin del mtodo ejecutar


} // fin de la clase SolicitudSaldo

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).

13.4.10 La clase Retiro


La clase Retiro (figura 13.22) extiende a Transaccion y representa una transaccin de retiro del
ATM. Esta clase se expande a partir del cdigo estructural para la misma, desarrollado en la figura
13.12. En el diagrama de clases de la figura 13.10 vimos que la clase Retiro tiene un atributo,
monto, que la lnea 6 implementa como campo int. La figura 13.9 modela las asociaciones entre
la clase Retiro y las clases Teclado y DispensadorEfectivo, para las que las lneas 7 y 8 implementan
los atributos de tipo referencia teclado y dispensadorEfectivo, respectivamente. La lnea 11 declara una constante que corresponde a la opcin de cancelacin en el men. Pronto veremos cmo
es que la clase utiliza esta constante.

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

Implementacin del caso de estudio del ATM

541

// comprueba si el dispensador de efectivo tiene suficiente dinero


if ( dispensadorEfectivo.haySuficienteEfectivoDisponible( monto ) )
{
// actualiza la cuenta implicada para reflejar el saldo
baseDatosBanco.cargar( obtenerNumeroCuenta(), monto );
dispensadorEfectivo.dispensarEfectivo( monto ); // dispensar efectivo
efectivoDispensado = true; // se dispens el efectivo
// instruye al usuario que tome efectivo
pantalla.mostrarLineaMensaje( \nSe dispenso su +
efectivo. Tomelo ahora. );
} // fin de if
else // el dispensador no tiene suficiente efectivo
pantalla.mostrarLineaMensaje(
\nNo hay suficiente efectivo disponible en el ATM. +
\n\nSeleccione un monto menor. );
} // fin de if
else // no hay suficiente dinero disponible en la cuenta del usuario
{
pantalla.mostrarLineaMensaje(
\nNo hay suficientes fondos en su cuenta. +
\n\nSeleccione un monto menor. );
} // fin de else
} // fin de if
else // el usuario eligi la opcin cancelar del men
{
pantalla.mostrarLineaMensaje( \nCancelando transaccion... );
return; // regresa al men principal porque el usuario cancel
} // fin de else
} while ( !efectivoDispensado );
} // fin del mtodo ejecutar
// muestra un men de montos de retiro y la opcin para cancelar;
// devuelve el monto elegido o 0 si el usuario elije cancelar
private int mostrarMenuDeMontos()
{
int opcionUsuario = 0; // variable local para almacenar el valor de retorno
Pantalla pantalla = obtenerPantalla(); // obtiene referencia a la pantalla
// arreglo de montos que corresponde a los nmeros del men
int montos[] = { 0, 20, 40, 60, 100, 200 };
// itera mientras no se haya elegido una opcin vlida
while ( opcionUsuario == 0 )
{
// muestra el men
pantalla.mostrarLineaMensaje( \nMenu de retiro: );
pantalla.mostrarLineaMensaje( 1 - $20 );
pantalla.mostrarLineaMensaje( 2 - $40 );
pantalla.mostrarLineaMensaje( 3 - $60 );

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

Implementacin del caso de estudio del ATM

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.

13.4.11 La clase Deposito


La clase Deposito (figura 13.23) extiende a Transaccion y representa una transaccin de depsito. En la figura 13.10 vimos que la clase Deposito tiene un atributo llamado monto, el cual
se implementa en la lnea 6 como un campo int. Las lneas 7 y 8 crean los atributos de referencia
teclado y ranuraDeposito, que implementan las asociaciones entre la clase Deposito y las clases Teclado y RanuraDeposito modeladas en la figura 13.9. La lnea 9 declara una constante
CANCELO, la cual corresponde al valor que introduce un usuario para cancelar. Pronto veremos cmo
es que la clase usa esta constante.

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

Implementacin del caso de estudio del ATM

545

// hace un abono a la cuenta para reflejar el depsito


baseDatosBanco.abonar( obtenerNumeroCuenta(), monto );
} // fin de if
else // no se recibi el sobre de depsito
{
pantalla.mostrarLineaMensaje( "\nNo inserto un sobre de " +
deposito, por lo que el ATM ha cancelado su transaccion. );
} // fin de else
} // fin de if
else // el usuario cancel en vez de introducir el monto
{
pantalla.mostrarLineaMensaje( \nCancelando transaccion... );
} // fin de else
} // fin del mtodo ejecutar
// pide al usuario que introduzca un monto a depositar en centavos
private double pedirMontoADepositar()
{
Pantalla pantalla = obtenerPantalla(); // obtiene referencia a la pantalla
// muestra el indicador
pantalla.mostrarMensaje( \nIntroduzca un monto a depositar en +
CENTAVOS (o 0 para cancelar): );
int entrada = teclado.obtenerEntrada(); // recibe la entrada del monto de
depsito
// comprueba si el usuario cancel o introdujo un monto vlido
if ( entrada == CANCELO )
return CANCELO;
else
{
return ( double ) entrada / 100; // devuelve el monto en dlares
} // fin de else
} // fin del mtodo pedirMontoADepositar
} // fin de la clase Deposito

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.

13.4.12 La clase CasoEstudioATM


La clase CasoEstudioATM (figura 13.24) es una clase simple que nos permite iniciar, o encender, el ATM
y evaluar la implementacin de nuestro modelo del sistema ATM. El mtodo main de la clase CasoEstudioATM (lneas 7 a 11) no hace nada ms que instanciar un nuevo objeto ATM llamado elATM (lnea 9),
e invoca a su mtodo run (lnea 10) para iniciar el ATM.

// CasoEstudioATM.java

// Programa controlador para el ejemplo prctico del ATM

3
4

public class CasoEstudioATM

// el mtodo main crea y ejecuta el ATM

public static void main( String[] args )

{
ATM elATM = new ATM();

elATM.run();

10
11
12

} // fin de main
} // fin de la clase CasoEstudioATM

Fig. 13.24

CasoEstudioATM.java inicia el ATM.

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!

Respuestas a los ejercicios de autoevaluacin

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.

Respuestas a los ejercicios de autoevaluacin


13.1

Verdadero. El signo menos () indica visibilidad privada.

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

// la clase Teclado representa el teclado de un ATM


public class Teclado
{
// no se han especificado atributos todava
// constructor sin argumentos
public Teclado()
{
} // fin del constructor de Teclado sin argumentos
// operaciones
public int obtenerEntrada()
{
} // fin del mtodo obtenerEntrada
} // fin de la clase Teclado

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

// La clase abstracta Transaccion representa una transaccin con el ATM


public abstract class Transaccion
{
// atributos
private int numeroCuenta; // indica la cuenta involucrada
private Pantalla pantalla; // la pantalla del ATM
private BaseDatosBanco baseDatosBanco; // base de datos de informacin de las cuentas

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

// constructor sin argumentos invocado por las subclases, usando super()


public Transaccion()
{
} // fin del constructor de Transaccion sin argumentos
// devuelve el nmero de cuenta
public int obtenerNumeroCuenta()
{
} // fin del mtodo obtenerNumeroCuenta
// devuelve referencia a la pantalla
public Pantalla obtenerPantalla()
{
} // fin del mtodo obtenerPantalla
// devuelve referencia a la base de datos del banco
public BaseDatosBanco obtenerBaseDatosBanco()
{
} // fin del mtodo obtenerBaseDatosBanco
// mtodo abstracto sobrescrito por las subclases
public abstract void ejecutar();
} // fin de la clase Transaccion

Fig. 13.26 Cdigo de Java para la clase Transaccion, con base en las figuras 13.9 y 13.10 (parte 2 de 2).

S-ar putea să vă placă și