Sistema bancario
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 85 de 87.
Este desafío te propone construir un Sistema Bancario que modele operaciones financieras del mundo real utilizando principios de POO.
Su sistema debe manejar diferentes tipos de cuenta como SavingsAccount y CheckingAccount, ambos extendiendo una clase base Account. Cada tipo de cuenta tiene comportamientos únicos: las cuentas de ahorro podrían generar intereses, mientras que las cuentas corrientes podrían tener protección contra sobregiros.
Piense en cómo modelar las transacciones. Una interfaz como Transactable podría definir métodos para deposit() y withdraw(). Considere el uso de excepciones personalizadas como InsufficientFundsException para manejar operaciones no válidas de manera elegante.
Una clase Bank podría gestionar múltiples cuentas y clientes, demostrando composición. Podrías aplicar el patrón Factory para crear diferentes tipos de cuentas, o usar el patrón Observer para notificar a los clientes sobre cambios en las cuentas.
Enfócate en el encapsulamiento para proteger datos sensibles como saldos y números de cuenta, y utiliza el polimorfismo para procesar diferentes tipos de cuenta de manera uniforme.
Desafío
Fácil¡Vamos a construir un Sistema Bancario completo que demuestre tu dominio de los principios de OOP! Crearás un sistema con diferentes tipos de cuenta, manejo de transacciones y una gestión adecuada de excepciones, todo organizado en múltiples archivos.
Organizarás tu código en siete archivos:
Transactable.java: Crea una interfaz que defina el contrato para las operaciones financieras. Debe declarar los métodosdeposit(double amount)ywithdraw(double amount), ambos devolviendo un booleano para indicar el éxito.InsufficientFundsException.java: Crea una excepción personalizada que extienda deException. El constructor debe aceptar el monto del retiro intentado y el saldo actual, creando un mensaje con el formato"Insufficient funds: attempted %.2f, available %.2f".Account.java: Crea una clase base abstracta que represente cualquier cuenta bancaria. Incluye campos privados paraaccountNumber(String) ybalance(double), un constructor que inicialice ambos, los getters apropiados, un setter protegido para el saldo (para que las subclases puedan modificarlo) y un método abstractogetAccountType()que devuelva un String. Implementa un métodogetDetails()que devuelva"%s (%s): $%.2f"con el saldo formateado a 2 decimales.SavingsAccount.java: Crea una clase que extienda deAccounte implementeTransactable. Añade un campo privado parainterestRate(double). El constructor recibe accountNumber, saldo inicial e interestRate. ImplementagetAccountType()para que devuelva"Savings". Paradeposit(), añade el monto al saldo y devuelve true. Parawithdraw(), si el monto excede el saldo, devuelve false; de lo contrario, réstalo y devuelve true. Añade un métodoapplyInterest()que aumente el saldo enbalance * interestRate(la tasa se almacena como una fracción, por lo que0.05significa 5%).CheckingAccount.java: Crea una clase que extienda deAccounte implementeTransactable. Añade un campo privado paraoverdraftLimit(double). El constructor recibe accountNumber, saldo inicial y overdraftLimit. ImplementagetAccountType()para que devuelva"Checking". Paradeposit(), añade el monto y devuelve true. Parawithdraw(), permite el retiro si el monto es menor o igual al saldo más overdraftLimit; devuelve false si excede este límite.Bank.java: Crea una clase que gestione las cuentas usando un ArrayList. Incluye los métodos:addAccount(Account account)- añade una cuenta al bancofindAccount(String accountNumber)- devuelve la Account o null si no se encuentratransfer(String fromAccount, String toAccount, double amount)- transfiere dinero entre cuentas, lanzandoInsufficientFundsExceptionsi la cuenta de origen no tiene fondos suficientes. En caso de éxito, devuelve"Transferred $%.2f from %s to %s"getTotalDeposits()- devuelve la suma de todos los saldos de las cuentas
Main.java: ¡Construye tu sistema bancario! Recibirás una cadena de comandos separados por comas:"SAVINGS":accountNumber:balance:interestRate"CHECKING":accountNumber:balance:overdraftLimit"DEPOSIT":accountNumber:amount"WITHDRAW":accountNumber:amount"TRANSFER":fromAccount:toAccount:amount"INTEREST":accountNumber
Procesa cada comando e imprime:
- SAVINGS/CHECKING:
"Account created: " + accountNumber - DEPOSIT:
"Deposited $%.2f to %s%n" - WITHDRAW:
"Withdrew $%.2f from %s%n"en caso de éxito, o"Withdrawal failed: " + accountNumber - TRANSFER: Imprime el mensaje de éxito o
"Transfer failed: " + e.getMessage() - INTEREST:
"Interest applied to " + accountNumber
Después de todos los comandos, imprime
"--- Bank Summary ---"seguido de los detalles de cada cuenta (usandogetDetails()) y finalmente"Total deposits: $%.2f%n"formateado a 2 decimales.
Recibirás una entrada: la cadena de comandos separados por comas.
Por ejemplo, con la entrada SAVINGS:SAV001:1000.00:0.05,CHECKING:CHK001:500.00:200.00,DEPOSIT:SAV001:250.00,WITHDRAW:CHK001:600.00,TRANSFER:SAV001:CHK001:100.00,INTEREST:SAV001, tu salida sería:
Account created: SAV001
Account created: CHK001
Deposited $250.00 to SAV001
Withdrew $600.00 from CHK001
Transferred $100.00 from SAV001 to CHK001
Interest applied to SAV001
--- Bank Summary ---
SAV001 (Savings): $1207.50
CHK001 (Checking): $0.00
Total deposits: $1207.50¡Observa cómo la cuenta corriente permite el retiro de $600 a pesar de tener solo $500 de saldo; esa es la protección contra sobregiros en acción! La cuenta de ahorros gana un 5% de interés sobre su saldo después de la transferencia. ¡Este desafío combina herencia, interfaces, polimorfismo, excepciones personalizadas y encapsulamiento en una aplicación bancaria realista!
Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Crear una instancia de Bank
// TODO: Dividir la entrada por comas para obtener los comandos individuales
// TODO: Procesar cada comando:
// - SAVINGS:accountNumber:balance:interestRate -> Crear SavingsAccount, imprimir "Account created: [accountNumber]"
// - CHECKING:accountNumber:balance:overdraftLimit -> Crear CheckingAccount, imprimir "Account created: [accountNumber]"
// - DEPOSIT:accountNumber:amount -> Depositar e imprimir "Deposited $[amount] to [accountNumber]"
// - WITHDRAW:accountNumber:amount -> Retirar e imprimir éxito o "Withdrawal failed: [accountNumber]"
// - TRANSFER:fromAccount:toAccount:amount -> Transferir e imprimir éxito o "Transfer failed: [exception message]"
// - INTEREST:accountNumber -> Aplicar intereses e imprimir "Interest applied to [accountNumber]"
// TODO: Después de todos los comandos, imprimir "--- Bank Summary ---"
// TODO: Imprimir los detalles de cada cuenta usando getDetails()
// TODO: Imprimir "Total deposits: $[total]" con formato de 2 decimales
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy14Desafíos finales
Plataforma de E-LearningSistema bancarioDesarrollo de personajes de videojuegosServicio de alquiler de vehículos3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator