caso de estudio - parte 2

Upload: yessi-gutierrez-asencio

Post on 14-Jan-2016

6 views

Category:

Documents


0 download

DESCRIPTION

CASOS DE ESTUDIO

TRANSCRIPT

  • Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos13

    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 atrofiadasDenise Levertov

    O b j e t i v o sEn 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.

  • 13.2 Inicio de la programacin de las clases del sistema ATM 511

    13.1 Introduccin

    13.2 Inicio de la programacin de las clases del sistema ATM

    13.3 Incorporacin de la herencia y el polimorfi smo en el sistema ATM

    13.4 Implementacin del caso de estudio del ATM13.4.1 La clase ATM13.4.2 La clase Pantalla13.4.3 La clase Teclado

    13.4.4 La clase DispensadorEfectivo13.4.5 La clase RanuraDeposito13.4.6 La clase Cuenta13.4.7 La clase BaseDatosBanco13.4.8 La clase Transaccion13.4.9 La clase SolicitudSaldo

    13.4.10 La clase Retiro13.4.11 La clase Deposito13.4.12 La clase CasoEstudioATM

    13.5 Conclusin

    Respuestas a los ejercicios de autoevaluacin

    13.1 IntroduccinEn el captulo 12 desarrollamos un diseo orientado a objetos para nuestro sistema ATM. Ahora imple-mentaremos 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 oportu-nidad 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].

    VisibilidadAhora aplicaremos modificadores de acceso a los miembros de nuestras clases. Ya presentamos en un ca-ptulo 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 em-pezar 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 co-locacin 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 in-cluyen 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].

    NavegabilidadAntes 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 (repre-sentadas 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

    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 re-ferencias 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 fle-chas 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 Solicitud-Saldo 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 Solici-tudSaldo 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, colo-caramos una flecha de navegabilidad en el extremo de la clase Pantalla de esta asociacin. Recuerde

    Fig. 13.1 Diagrama de clases con marcadores de visibilidad.

    ATM

    usuarioAutenticado : Boolean = false

    SolicitudSaldo

    numeroCuenta : Integer

    DispensadorEfectivo

    cuenta : Integer = 500

    RanuraDeposito

    Pantalla

    Teclado

    Retiro

    numeroCuenta : Integer monto : Double

    BaseDatosBanco

    Deposito

    numeroCuenta : Integer monto : Double

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

    Cuenta

    numeroCuenta : Integer nip : Integer saldoDisponible : Double saldoTotal : Double

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

    + ejecutar()

    + ejecutar()+ mostrarMensaje()

    + dispensarEfectivo()+ haySuficienteEfectivoDisponible() : Boolean

    + obtenerEntrada() : Integer+ ejecutar()

    + seRecibioSobreDeposito : Boolean

  • 13.2 Inicio de la programacin de las clases del sistema ATM 513

    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 colo-car 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 incor-porar el concepto orientado a objetos de la herencia].

    Implementacin del sistema ATM a partir de su diseo de UMLAhora 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. Usare-mos 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 recep-tculo 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

    Fig. 13.2 Diagrama de clases con flechas de navegabilidad.

    Accede a/modifica un saldode cuenta a travs de

    Ejecuta

    1

    1

    1

    1 1

    1

    1

    1

    1

    1 1 1 1

    1

    0..*

    0..110..1

    0..1 0..10..1

    1Contiene

    Autentica al usuario contra

    Teclado

    Retiro

    RanuraDeposito

    ATM

    DispensadorEfectivo

    Pantalla

    Cuenta

    BaseDatosBanco

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

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

    3. Use las asociaciones descritas en el diagrama de clases para declarar las referencias a otros ob-jetos. 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 cons-tructor 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 mto-dos 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.

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

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

    2 public class Retiro

    3 {

    4 // constructor sin argumentos

    5 public Retiro()

    6 {

    7 } // fin del constructor de Retiro sin argumentos

    8 } // 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.

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

    2 public class Retiro

    3 {

    4 // atributos

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

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

    7

    8 // constructor sin argumentos

    9 public Retiro()

    10 {

    11 } // fin del constructor de Retiro sin argumentos

    12 } // fin de la clase Retiro

  • Ejercicios de autoevaluacin de la seccin 13.2 515

    Ejercicios de autoevaluacin de la seccin 13.213.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.

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

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

    2 public class Retiro

    3 {

    4 // atributos

    5 private int numeroCuenta; // cuenta de la que se retirarn los fondos

    6 private double monto; // monto a retirar

    7

    8 // referencias a los objetos asociados

    9 private Pantalla pantalla; // pantalla del ATM

    10 private Teclado teclado; // teclado del ATM

    11 private DispensadorEfectivo dispensadorEfectivo; // dispensador de efectivo del ATM

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

    13

    14 // constructor sin argumentos

    15 public Retiro()

    16 {

    17 } // fin del constructor de Retiro sin argumentos

    18 } // 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.

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

    2 public class Retiro

    3 {

    4 // atributos

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

    6 private double monto; // monto a retirar

    7

    8 // referencias a los objetos asociados

    9 private Pantalla pantalla; // pantalla del ATM

    10 private Teclado teclado; // teclado del ATM

    11 private DispensadorEfectivo dispensadorEfectivo; // dispensador de efectivo del ATM12 private BaseDatosBanco baseDatosBanco; // base de datos de informacin de las

    cuentas

    13

    14 // constructor sin argumentos

    15 public Retiro()

    16 {

    17 } // fin del constructor de Retiro sin argumentos

    18

    19 // operaciones

    20 public void ejecutar()

    21 {

    22 } // fin del mtodo ejecutar

    23 } // fin de la clase Retiro

  • 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 he-rencia. 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 c-digo 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 trans-acciones 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 ope-racin (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 trans-acciones. 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 cla-ses. Colocamos la funcionalidad comn en una superclase, Transaccion, que las clases SolicitudSaldo, Retiro y Deposito extienden.

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

    SolicitudSaldo

    - numeroCuenta : Integer

    Retiro

    - numeroCuenta : Integer- monto : Double

    Deposito

    - numeroCuenta : Integer- monto : Double

    + ejecutar()

    + ejecutar() + ejecutar()

    GeneralizacinUML 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 polimorfi smo en el sistema ATM 517

    SolicitudSaldo, Retiro y Deposito. Las flechas con puntas triangulares huecas indican que las cla-ses SolicitudSaldo, Retiro y Deposito extienden a la clase Transaccion. Se dice que la clase Trans-accion 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.

    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.

    Transaccin

    numeroCuenta: Integer

    + obtenerNumeroCuenta()+ ejecutar()

    SolicitudSaldo

    + ejecutar()

    Retiro

    + ejecutar()

    monto : Double

    Deposito

    + ejecutar()

    monto : Double

    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 obtenerNumero-Cuenta 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 compar-ten la operacin ejecutar, por lo que colocamos el mtodo public ejecutar en la superclase Trans-accion. 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, de-claramos el mtodo ejecutar como abstract en la superclase Transaccion. Cualquier clase que con-tenga 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 apare-cen 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 dis-tinta del mtodo sobrescrito.

    Procesamiento de objetos Transaccion mediante el polimorfismoEl 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 refe-rencia 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 invocar el mtodo ejecutar, se hace una llamada a la versin de ejecutar de SolicitudSaldo.

    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 modifica-ciones 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 nun-ca 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 de-fine el concepto de lo que significa ser una transaccin que tiene un nmero de cuenta y puede ejecu-tarse. 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 perspec-tiva 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 subcla-ses, 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 DepositoLas subclases SolicitudSaldo, Retiro y Deposito heredan el atributo numeroCuenta de la super-clase 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 super-clase Transaccion; en la superclase slo colocamos las caractersticas comunes para todas las subcla-ses, 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 TransaccionLa 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 transac-cin 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 direc-tamente 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 asocia-cin, 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 polimorfi smo en el sistema ATM 519

    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 pue-dan 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 aso-ciaciones 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 Base-DatosBanco y con la Pantalla.

    La figura 13.1 muestra los atributos y las operaciones con marcadores de visibilidad. Ahora pre-sentamos 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-

    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.

    Accede a/modifica el saldode una cuenta a travs de

    Ejecuta

    1

    1

    1

    1 1

    1

    1

    1

    1

    1 1 1 1

    11

    1

    0..*

    0..110..1

    0..1 0..1

    0..1 0..10..1

    1Contiene

    Autentica al usuario contra

    Teclado

    Transaccin

    SolicitudSaldo

    RetiroRanuraDeposito

    ATM

    DispensadorEfectivo

    Pantalla

    Deposito

    Cuenta

    BaseDatosBanco

  • 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.1Un 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, m-todos 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.

    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.

    ATM

    usuarioAutenticado : Boolean = false

    SolicitudSaldo

    DispensadorEfectivo

    cuenta : Integer = 500

    RanuraDeposito

    Pantalla

    TecladoRetiro

    monto : Double

    BaseDatosBanco

    Deposito

    monto : Double

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

    Cuenta

    numeroCuenta : Integer nip : Integer saldoDisponible : Double saldoTotal : Double

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

    + ejecutar()

    Transaccin

    numeroCuenta : Integer

    + obtenerNumeroCuenta()+ ejecutar()

    + ejecutar()

    + mostrarMensaje()

    + dispensarEfectivo()+ haySuficienteEfectivoDisponible() : Boolean

    + obtenerEntrada() : Integer

    + ejecutar()

    + seRecibioSobre() : Boolean

  • 13.3 Incorporacin de la herencia y el polimorfi smo 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 de-claracin 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.

    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 abs-tract ejecutar de la superclase Transaccion. Las referencias teclado y dispensador-Efectivo (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.

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

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

    2 public class Retiro extends Transaccion

    3 {

    4 } // 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 1 de 2).

    1 // Retiro.java

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

    3 public class Retiro extends Transaccion

    4 {

    5 // atributos

    6 private double monto; // monto a retirar

    7 private Teclado teclado; // referencia al teclado

    8 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

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

    Observacin de ingeniera de software 13.2Varias 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 cuida-dosamente, 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 para indicar una relacin de generalizacin.a) punta con relleno slidob) punta triangular sin rellenoc) punta hueca en forma de diamanted) punta lineal

    13.5 Indique si el siguiente enunciado es verdadero o falso y, si es falso, explique por qu: UML requiere que subraye-mos 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 ATMEsta seccin contiene la implementacin funcional completa de 673 lneas del sistema ATM. Consi-deramos 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 pre-sentados 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 especifi-que todos los atributos y operaciones requeridos para completar la implementacin del ATM. sta es

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

    15 // mtodo que sobrescribe a ejecutar

    16 @Override

    17 public void ejecutar()

    18 {

    19 } // fin del mtodo ejecutar

    20 } // fin de la clase Retiro

  • 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 accio-nes 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 atribu-tos 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 mo-deladas 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).

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

    1 // ATM.java

    2 // Representa a un cajero automtico

    3

    4 public class ATM

    5 {

    6 private boolean usuarioAutenticado; // indica si el usuario es autenticado

    7 private int numeroCuentaActual; // nmero de cuenta actual del usuario

    8 private Pantalla pantalla; // pantalla del ATM

    9 private Teclado teclado; // teclado del ATM

    10 private DispensadorEfectivo dispensadorEfectivo; // dispensador de efectivo del ATM

    11 private RanuraDeposito ranuraDeposito; // ranura de depsito del ATM12 private BaseDatosBanco baseDatosBanco; // base de datos de informacin de las

    cuentas

    13

    14 // constantes correspondientes a las opciones del men principal

    15 private static final int SOLICITUD_SALDO = 1;

    16 private static final int RETIRO = 2;

    17 private static final int DEPOSITO = 3;

    18 private static final int SALIR = 4;

    19

    20 // el constructor sin argumentos de ATM inicializa las variables de instancia

    21 public ATM()

    22 {

    23 usuarioAutenticado = false; // al principio, el usuario no est autenticado

    24 numeroCuentaActual = 0; // al principio, no hay nmero de cuenta

    25 pantalla = new Pantalla(); // crea la pantalla

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

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

    26 teclado = new Teclado(); // crea el teclado27 dispensadorEfectivo = new DispensadorEfectivo(); // crea el dispensador de

    efectivo28 ranuraDeposito = new RanuraDeposito(); // crea la ranura de depsito29 baseDatosBanco = new BaseDatosBanco(); // crea la base de datos de informacin

    de cuentas30 } // fin del constructor sin argumentos de ATM31 32 // inicia el ATM33 public void run()34 {35 // da la bienvenida al usuario y lo autentica; realiza transacciones36 while ( true )37 {38 // itera mientras el usuario no haya sido autenticado39 while ( !usuarioAutenticado )40 {41 pantalla.mostrarLineaMensaje( \nBienvenido! );42 autenticarUsuario(); // autentica el usuario43 } // fin de while44 45 realizarTransacciones(); // ahora el usuario est autenticado46 usuarioAutenticado = false; // restablece antes de la siguiente sesin con

    el ATM

    47 numeroCuentaActual = 0; // restablece antes de la siguiente sesin con el ATM

    48 pantalla.mostrarLineaMensaje( \nGracias! Adios! );49 } // fin de while50 } // fin del mtodo run51 52 // trata de autenticar al usuario en la base de datos53 private void autenticarUsuario()54 {55 pantalla.mostrarMensaje( \nEscriba su numero de cuenta: );56 int numeroCuenta = teclado.obtenerEntrada(); // recibe como entrada el nmero

    de cuenta57 pantalla.mostrarMensaje( \nEscriba su NIP: ); // pide el NIP58 int nip = teclado.obtenerEntrada(); // recibe como entrada el NIP59 60 // establece usuarioAutenticado con el valor booleano devuelto por la base de

    datos61 usuarioAutenticado =62 baseDatosBanco.autenticarUsuario( numeroCuenta, nip );63 64 // verifica si la autenticacin tuvo xito65 if ( usuarioAutenticado )66 {67 numeroCuentaActual = numeroCuenta; // guarda el # de cuenta del usuario68 } // fin de if69 else70 pantalla.mostrarLineaMensaje(71 Numero de cuenta o NIP invalido. Intente de nuevo. );72 } // fin del mtodo autenticarUsuario73 74 // muestra el men principal y realiza transacciones75 private void realizarTransacciones()76 {77 // variable local para almacenar la transaccin que se procesa actualmente78 Transaccion transaccionActual = null;

  • 13.4 Implementacin del caso de estudio del ATM 525

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

    79 80 boolean usuarioSalio = false; // el usuario no ha elegido salir81 82 // itera mientras que el usuario no haya elegido la opcin para salir del

    sistema83 while ( !usuarioSalio )84 {85 // muestra el men principal y obtiene la seleccin del usuario86 int seleccionMenuPrincipal = mostrarMenuPrincipal();87 88 // decide cmo proceder, con base en la opcin del men seleccionada por el

    usuario89 switch ( seleccionMenuPrincipal )90 {91 // el usuario eligi realizar uno de tres tipos de transacciones92 case SOLICITUD_SALDO:93 case RETIRO:94 case DEPOSITO:95 96 // inicializa como nuevo objeto del tipo elegido97 transaccionActual =98 crearTransaccion( seleccionMenuPrincipal );99 100 transaccionActual.ejecutar(); // ejecuta la transaccin101 break;102 case SALIR: // el usuario eligi terminar la sesin103 pantalla.mostrarLineaMensaje( "\nCerrando el sistema..." );104 usuarioSalio = true; // esta sesin con el ATM debe terminar105 break;106 default: // el usuario no introdujo un entero de 1 a 4107 pantalla.mostrarLineaMensaje(108 "\nNo introdujo una seleccion valida. Intente de nuevo." );109 break;110 } // fin de switch111 } // fin de while112 } // fin del mtodo realizarTransacciones113 114 // muestra el men principal y devuelve una seleccin de entrada115 private int mostrarMenuPrincipal()116 {117 pantalla.mostrarLineaMensaje( \nMenu principal: );118 pantalla.mostrarLineaMensaje( 1 - Ver mi saldo );119 pantalla.mostrarLineaMensaje( 2 - Retirar efectivo );120 pantalla.mostrarLineaMensaje( 3 - Depositar fondos );121 pantalla.mostrarLineaMensaje( 4 - Salir\n );122 pantalla.mostrarMensaje( Escriba una opcion: );123 return teclado.obtenerEntrada(); // devuelve la opcion seleccionada por el

    usuario124 } // fin del mtodo mostrarMenuPrincipal125 126 // devuelve un objeto de la subclase especificada de Transaccion127 private Transaccion crearTransaccion( int tipo )128 {129 Transaccion temp = null; // variable temporal Transaccion130

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

    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, Dispen-sadorEfectivo 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 imple-mentacin slo estamos simulando la base de datos del banco, por lo que ATM crea el objeto BaseDatos-Banco 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 im-plementar 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 usuarioEn 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,

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

    131 // determina qu tipo de Transaccion crear

    132 switch ( tipo )

    133 {

    134 case SOLICITUD_SALDO: // crea una nueva transaccin SolicitudSaldo

    135 temp = new SolicitudSaldo(

    136 numeroCuentaActual, pantalla, baseDatosBanco );

    137 break;

    138 case RETIRO: // crea una nueva transaccin Retiro

    139 temp = new Retiro( numeroCuentaActual, pantalla,

    140 baseDatosBanco, teclado, dispensadorEfectivo );

    141 break;

    142 case DEPOSITO: // crea una nueva transaccin Deposito

    143 temp = new Deposito( numeroCuentaActual, pantalla,

    144 baseDatosBanco, teclado, ranuraDeposito );

    145 break;

    146 } // fin de switch

    147

    148 return temp; // devuelve el objeto recin creado

    149 } // fin del mtodo crearTransaccion

    150 } // fin de la clase ATM

  • 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 auten-ticar al usuario, antes de permitir que ocurran transacciones. La lnea 55 del mtodo autenticar-Usuario 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 lla-mada 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 intro-ducidos 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 usuario-Autenticado 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 inten-tar 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 si-gue 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 realizar-Transacciones de la clase ATM.

    Realizar transaccionesEl mtodo realizarTransacciones (lneas 75 a 112) lleva a cabo una sesin con el ATM para un usua-rio 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 seleccio-n. 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 (decla-rado 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 va-riable 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 selec-cionMenuPrincipal 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 instan-ciado 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 transaccio-nes mediante el polimorfismo. Por ejemplo, si el usuario opta por realizar una solicitud de saldo, selec-cionMenuPrincipal 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 in-vocacin de transaccionActual.ejecutar() produce como resultado la invocacin a la versin de ejecutar que corresponde a SolicitudSaldo.

    Creacin de una transaccinEl 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. Recuer-de 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 inicia-lizar 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 analizare-mos las clases de transacciones con ms detalle.

    Salir del men principal y procesar selecciones invlidasDespus 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 obs-tante, 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 (!usuario-Salio) 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 in-tentar de nuevo.

    Esperar al siguiente usuario del ATMCuando 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 des-pedida antes de que el ATM inicie de nuevo y d la bienvenida al nuevo usuario.

    13.4.2 La clase PantallaLa clase Pantalla (figura 13.14) representa la pantalla del ATM y encapsula todos los aspectos rela-cionados 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.

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

    1 // Pantalla.java

    2 // Representa a la pantalla del ATM

    3

    4 public class Pantalla

    5 {

    6 // muestra un mensaje sin un retorno de carro

    7 public void mostrarMensaje( String mensaje )

    8 {

    9 System.out.print( mensaje );

    10 } // fin del mtodo mostrarMensaje

    11

    12 // muestra un mensaje con un retorno de carro

    13 public void mostrarLineaMensaje( String mensaje )

    14 {

    15 System.out.println( mensaje );

    16 } // fin del mtodo mostrarLineaMensaje

    17

    18 // muestra un monto en dlares

    19 public void mostrarMontoDolares( double monto )

    20 {

    21 System.out.printf( $%,.2f, monto );

    22 } // fin del mtodo mostrarMontoDolares

    23 } // fin de la clase Pantalla

    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 compu-tadora 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 referen-cia 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 Captulo 13 Caso de estudio del ATM, Parte 2: Implementacin de un diseo orientado a objetos

    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 in-formacin 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 obtener-Entrada 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 l-nea 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 dispo-nible mediante una llamada a haySuficienteEfectivoDisponible. Por ende, dispensarEfectivo tan slo simula el proceso de dispensar la cantidad solicitada sin verificar si en realidad hay suficien-te efectivo disponible.

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

    Fig. 13.16 La clase DispensadorEfectivo representa al dispensador de efectivo del ATM (parte 1 de 2).

    1 // Teclado.java

    2 // Representa el teclado del ATM 3 import java.util.Scanner; // el programa usa a Scanner para obtener la entrada del

    usuario

    4

    5 public class Teclado

    6 {

    7 private Scanner entrada; // lee datos de la lnea de comandos

    8

    9 // el constructor sin argumentos inicializa el objeto Scanner

    10 public Teclado()

    11 {

    12 entrada = new Scanner( System.in );

    13 } // fin del constructor sin argumentos de Teclado

    14

    15 // devuelve un valor entero introducido por el usuario

    16 public int obtenerEntrada()

    17 {

    18 return entrada.nextInt(); // suponemos que el usuario introduce un entero

    19 } // fin del mtodo obtenerEntrada

    20 } // fin de la clase Teclado

    1 // DispensadorEfectivo.java

    2 // Representa al dispensador de efectivo del ATM

    3

  • 13.4 Implementacin del caso de estudio del ATM 531

    El mtodo haySuficienteEfectivoDisponible (lneas 24 a 32) tiene un parmetro llamado monto, 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 nme-ro 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 efec-tivo; la clase DispensadorEfectivo no puede interactuar de manera directa con Pantalla.

    13.4.5 La clase RanuraDepositoLa 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

    Fig. 13.16 La clase DispensadorEfectivo representa al dispensador de efectivo del ATM (parte 2 de 2).

    4 public class DispensadorEfectivo

    5 {

    6 // el nmero inicial predeterminado de billetes en el dispensador de efectivo

    7 private final static int CUENTA_INICIAL = 500;

    8 private int cuenta; // nmero restante de billetes de $20

    9 10 // el constructor sin argumentos de DispensadorEfectivo inicializa cuenta con el

    valor predeterminado

    11 public DispensadorEfectivo()

    12 {

    13 cuenta = CUENTA_INICIAL; // establece el atributo cuenta al valor predeterminado

    14 } // fin del constructor de DispensadorEfectivo

    15

    16 // simula la accin de dispensar el monto especificado de efectivo

    17 public void dispensarEfectivo( int monto )

    18 {

    19 int billetesRequeridos = monto / 20; // nmero de billetes de $20 requeridos

    20 cuenta -= billetesRequeridos; // actualiza la cuenta de billetes

    21 } // fin del mtodo dispensarEfectivo

    22

    23 // indica si el dispensador de efectivo puede dispensar el monto deseado

    24 public boolean haySuficienteEfectivoDisponible( int monto )

    25 {

    26 int billetesRequeridos = monto / 20; // nmero de billetes de $20 requeridos

    27

    28 if ( cuenta >= billetesRequeridos )

    29 return true; // hay suficientes billetes disponibles

    30 else

    31 return false; // no hay suficientes billetes disponibles

    32 } // fin del mtodo haySuficienteEfectivoDisponible

    33 } // fin de la clase DispensadorEfectivo

  • 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 con un mtodo: seRecibio-Sobre (lneas 8 a 11), el cual indica si se recibi un sobre de depsito.

    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 so-bre 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.

    Fig. 13.18 La clase Cuenta representa a una cuenta bancaria (parte 1 de 2).

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

    1 // RanuraDeposito.java

    2 // Representa a la ranura de depsito del ATM

    3

    4 public class RanuraDeposito

    5 {

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

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

    8 public boolean seRecibioSobre()

    9 {

    10 return true; // se recibi el sobre

    11 } // fin del mtodo seRecibioSobre

    12 } // fin de la clase RanuraDeposito

    1 // Cuenta.java

    2 // Representa a una cuenta bancaria

    3

    4 public class Cuenta

    5 {

    6 private int numeroCuenta; // nmero de cuenta

    7 private int nip; // NIP para autenticacin

    8 private double saldoDisponible; // fondos disponibles para retirar

    9 private double saldoTotal; // fondos disponibles + depsitos pendientes

  • 13.4 Implementacin del caso de estudio del ATM 533

    Fig. 13.18 La clase Cuenta representa a una cuenta bancaria (parte 2 de 2).

    10 11 // el constructor de Cuenta inicializa los atributos

    12 public Cuenta( int elNumeroDeCuenta, int elNIP,

    13 double elSaldoDisponible, double elSaldoTotal )

    14 {

    15 numeroCuenta = elNumeroDeCuenta;

    16 nip = elNIP;

    17 saldoDisponible = elSaldoDisponible;

    18 saldoTotal = elSaldoTotal;

    19 } // fin del constructor de Cuenta

    20

    21 // determina si un NIP especificado por el usuario coincide con el NIP en la Cuenta

    22 public boolean validarNIP( int nipUsuario )

    23 {

    24 if ( nipUsuario == nip )

    25 return true;

    26 else

    27 return false;

    28 } // fin del mtodo validarNIP

    29

    30 // devuelve el saldo disponible

    31 public double obtenerSaldoDisponible()

    32 {

    33 return saldoDisponible;

    34 } // fin de obtenerSaldoDisponible

    35

    36 // devuelve el saldo total

    37 public double obtenerSaldoTotal()

    38 {

    39 return saldoTotal;

    40 } // fin del mtodo obtenerSaldoTotal

    41

    42 // abona un monto a la cuenta

    43 public void abonar( double monto )

    44 {

    45 saldoTotal += monto; // lo suma al saldo total

    46 } // fin del mtodo abonar

    47

    48 // carga un monto a la cuenta

    49 public void cargar( double monto )

    50 {

    51 saldoDisponible -= monto; // lo resta del saldo disponible

    52 saldoTotal -= monto; // lo resta del saldo total

    53 } // fin del mtodo cargar

    54

    55 // devuelve el nmero de cuenta

    56 public int obtenerNumeroCuenta()

    57 {

    58 return numeroCuenta;

    59 } // fin del mtodo obtenerNumeroCuenta60 } // fin de la clase Cuenta

  • 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). Recuer-de 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 dis-ponible 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 in-teracta para acceder a la informacin de la cuenta de un usuario y modificarla. En el captulo 28 estu-diaremos 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.

    Fig. 13.19 La clase BaseDatosBanco representa a la base de datos de informacin sobre las cuentas del banco (parte 1 de 3).

    1 // BaseDatosBanco.java

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

    3

    4 public class BaseDatosBanco

    5 {

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

    7

    8 // el constructor sin argumentos de BaseDatosBanco inicializa a cuentas

    9 public BaseDatosBanco()

    10 {

  • 13.4 Implementacin del caso de estudio del ATM 535

    Fig. 13.19 La clase BaseDatosBanco representa a la base de datos de informacin sobre las cuentas del banco (parte 2 de 3).

    11 cuentas = new Cuenta[ 2 ]; // slo 2 cuentas para probar12 cuentas[ 0 ] = new Cuenta( 12345, 54321, 1000.0, 1200.0 );13 cuentas[ 1 ] = new Cuenta( 98765, 56789, 200.0, 200.0 );14 } // fin del constructor sin argumentos de BaseDatosBanco15 16 // obtiene el objeto Cuenta que contiene el nmero de cuenta especificado17 private Cuenta obtenerCuenta( int numeroCuenta )18 {19 // itera a travs de cuentas, buscando el nmero de cuenta que coincida20 for ( Cuenta cuentaActual : cuentas )21 {22 // devuelve la cuenta actual si encuentra una coincidencia23 if ( cuentaActual.obtenerNumeroCuenta() == numeroCuenta )24 return cuentaActual;25 } // fin de for26 27 return null; // si no se encontr una cuenta que coincida, devuelve null28 } // fin del mtodo obtenerCuenta29 30 // determina si el nmero de cuenta y el NIP especificados por el usuario coinciden31 // con los de una cuenta en la base de datos32 public boolean autenticarUsuario( int numeroCuentaUsuario, int nipUsuario )33 {34 // trata de obtener la cuenta con el nmero de cuenta35 Cuenta cuentaUsuario = obtenerCuenta( numeroCuentaUsuario );36 37 // si la cuenta existe, devuelve el resultado del mtodo validarNIP de Cuenta38 if ( cuentaUsuario != null )39 return cuentaUsuario.validarNIP( nipUsuario );40 else41 return false; // no se encontr el nmero de cuenta, por lo que devuelve false42 } // fin del mtodo autenticarUsuario43 44 // devuelve el saldo disponible de la Cuenta con el nmero de cuenta especificado45 public double obtenerSaldoDisponible( int numeroCuentaUsuario )46 {47 return obtenerCuenta( numeroCuentaUsuario ).obtenerSaldoDisponible();48 } // fin del mtodo obtenerSaldoDisponible49 50 // devuelve el saldo total de la Cuenta con el nmero de cuenta especificado51 public double obtenerSaldoTotal( int numeroCuentaUsuario )52 {53 return obtenerCuenta( numeroCuentaUsuario ).obtenerSaldoTotal();54 } // fin del mtodo obtenerSaldoTotal55 56 // abona un monto a la Cuenta a travs del nmero de cuenta especificado57 public void abonar( int numeroCuentaUsuario, double monto )58 {59 obtenerCuenta( numeroCuentaUsuario ).abonar( monto );60 } // fin del mtodo abonar61

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

    Determinamos un atributo de tipo referencia para la clase BaseDatosBanco con base en su rela-cin 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 BaseDatos-Banco 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 obje-tos 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 locali-zar la Cuenta del usuario, la BaseDatosBanco compara el valor devuelto por el mtodo obtenerNumero-Cuenta 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 argu-mentos, 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 obte-nerCuenta 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 compara-cin 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 obtener-SaldoDisponible (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-

    Fig. 13.19 La clase BaseDatosBanco representa a la base de datos de informacin sobre las cuentas del banco (parte 3 de 3).

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

    63 public void cargar( int numeroCuentaUsuario, double monto )

    64 {

    65 obtenerCuenta( numeroCuentaUsuario ).cargar( monto );

    66 } // fin del mtodo cargar

    67 } // fin de la clase BaseDatosBanco

  • 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 numero-CuentaUsuario 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 TransaccionLa clase Transaccion (figura 13.20) es una superclase abstracta que representa la nocin de una trans-accin 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 atribu-tos 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.

    Fig. 13.20 La superclase abstracta Transaccion representa una transaccin con el ATM (parte 1 de 2).

    1 // Transaccion.java

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

    3

    4 public abstract class Transaccion

    5 {

    6 private int numeroCuenta; // indica la cuenta implicada

    7 private Pantalla pantalla; // pantalla del ATM

    8 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,

    12 BaseDatosBanco baseDatosBancoATM )

    13 {

    14 numeroCuenta = numeroCuentaUsuario;

    15 pantalla = pantallaATM;

    16 baseDatosBanco = baseDatosBancoATM;

    17 } // fin del constructor de Transaccion

    18

    19 // devuelve el nmero de cuenta

    20 public int obtenerNumeroCuenta()

    21 {

    22 return numeroCuenta;

    23 } // fin del mtodo obtenerNumeroCuenta

    24

    25 // devuelve una referencia a la pantalla

    26 public Pantalla obtenerPantalla()

    27 {

    28 return pantalla;

    29 } // fin del mtodo obtenerPantalla

    30

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

    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), obtener-Pantalla (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 pro-veer 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 solici-tud de saldo con el ATM. SolicitudSaldo no tiene atributos propios, pero hereda los atributos numero-Cuenta, 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).

    31 // devuelve una referencia a la base de datos del banco

    32 public BaseDatosBanco obtenerBaseDatosBanco()

    33 {

    34 return baseDatosBanco;

    35 } // fin del mtodo obtenerBaseDatosBanco

    36

    37 // realiza la transaccin (cada subclase sobrescribe este mtodo)

    38 abstract public void ejecutar();

    39 } // fin de la clase Transaccion

    Fig. 13.20 La superclase abstracta Transaccion representa una transaccin con el ATM (parte 2 de 2).

    Fig. 13.21 La clase SolicitudSaldo representa a una transaccin de solicitud de saldo en el ATM (parte 1 de 2).

    1 // SolicitudSaldo.java

    2 // Representa una transaccin de solicitud de saldo en el ATM

    3

    4 public class SolicitudSaldo extends Transaccion

    5 {

    6 // constructor de SolicitudSaldo

    7 public SolicitudSaldo( int numeroCuentaUsuario, Pantalla pantallaATM,

    8 BaseDatosBanco baseDatosBanco )

    9 {

    10 super( numeroCuentaUsuario, pantallaATM, baseDatosBanco );

    11 } // fin del constructor de SolicitudSaldo

    12

    13 // realiza la transaccin

    14 @Override

    15 public void ejecutar()

    16 {

  • 13.4 Implementacin del caso de estudio del ATM 539

    La clase SolicitudSaldo sobrescribe el mtodo abstracto ejecutar de Transaccin para pro-veer 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 n-mero 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 de-clara una constante que corresponde a la opcin de cancelacin en el men. Pronto veremos cmo es que la clase utiliza esta constante.

    Fig. 13.21 La clase SolicitudSaldo representa a una transaccin de solicitud de saldo en el ATM (parte 2 de 2).

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

    18 BaseDatosBanco baseDatosBanco = obtenerBaseDatosBanco();

    19 Pantalla pantalla = obtenerPantalla();

    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: );