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.
Tu sistema debería gestionar distintos 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.
Piensa en cómo modelar las transacciones. Una interfaz como Transactable podría definir métodos para deposit() y withdraw(). Considera usar excepciones personalizadas como InsufficientFundsException para gestionar las operaciones no válidas correctamente.
Una clase Bank podría gestionar varias cuentas y clientes, demostrando la composición. Podrías aplicar el patrón Factory para crear diferentes tipos de cuenta o usar el patrón Observer para notificar a los clientes sobre los cambios en las cuentas.
Concéntrate en la encapsulación para proteger datos confidenciales como los saldos y los números de cuenta, y usa el polimorfismo para procesar de manera uniforme diferentes tipos de cuenta.
Desafío
Fácil¡Construyamos un Sistema Bancario completo que demuestre tu dominio de los principios de OOP! Crearás un sistema con diferentes tipos de cuentas, gestión de transacciones y una gestión adecuada de excepciones: todo organizado en varios 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 si la operación tuvo éxito.InsufficientFundsException.java: Crea una excepción personalizada que extiendaException. El constructor debe aceptar el importe del retiro intentado y el saldo actual, creando un mensaje con el formatoInsufficient funds: attempted [amount], available [balance].Account.java: Crea una clase base abstracta que represente cualquier cuenta bancaria. Incluye campos privados paraaccountNumber(String) ybalance(double), un constructor que inicialice ambos, getters apropiados, un setter protegido para balance (para que las subclases puedan modificarlo) y un método abstractogetAccountType()que devuelva un String. Implementa un métodogetDetails()que devuelva"[accountNumber] ([accountType]): $[balance]"con el balance formateado con 2 decimales.SavingsAccount.java: Crea una clase que extiendaAccounte implementeTransactable. Añade un campo privado parainterestRate(double). El constructor recibe accountNumber, balance inicial e interestRate. ImplementagetAccountType()para que devuelva"Savings". Paradeposit(), suma el importe al balance y devuelve true. Parawithdraw(), si el importe supera el balance, devuelve false; de lo contrario, resta el importe y devuelve true. Añade un métodoapplyInterest()que incremente el balance enbalance * interestRate(la tasa se almacena como una fracción, por lo que0.05significa 5%).CheckingAccount.java: Crea una clase que extiendaAccounte implementeTransactable. Añade un campo privado paraoverdraftLimit(double). El constructor recibe accountNumber, balance inicial y overdraftLimit. ImplementagetAccountType()para que devuelva"Checking". Paradeposit(), suma el importe y devuelve true. Parawithdraw(), permite el retiro si el importe es menor o igual que el balance más overdraftLimit; devuelve false si supera este límite.Bank.java: Crea una clase que gestione las cuentas mediante 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 y lanzaInsufficientFundsExceptionsi la cuenta de origen no tiene fondos suficientes. Si tiene éxito, devuelve"Transferred $[amount] from [fromAccount] to [toAccount]"getTotalDeposits()- devuelve la suma de los balances de todas las cuentas
Main.java: ¡Construye tu sistema bancario! Recibirás una cadena de comandos separados por comas:SAVINGS:accountNumber:balance:interestRateCHECKING:accountNumber:balance:overdraftLimitDEPOSIT:accountNumber:amountWITHDRAW:accountNumber:amountTRANSFER:fromAccount:toAccount:amountINTEREST:accountNumber
Procesa cada comando e imprime:
- SAVINGS/CHECKING:
Account created: [accountNumber] - DEPOSIT:
Deposited $[amount] to [accountNumber] - WITHDRAW:
Withdrew $[amount] from [accountNumber]si tiene éxito, oWithdrawal failed: [accountNumber] - TRANSFER: imprime el mensaje de éxito o
Transfer failed: [exception message] - 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: $[total]formateado con 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.50Observa cómo la cuenta corriente permite retirar $600 a pesar de tener solo un balance de $500: ¡esa es la protección contra sobregiros en acción! La cuenta de ahorros obtiene un 5% de interés sobre su balance después de la transferencia. ¡Este desafío combina herencia, interfaces, polimorfismo, excepciones personalizadas y encapsulación 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: Crea una instancia de Bank
// TODO: Separa la entrada por comas para obtener los comandos individuales
// TODO: Procesa cada comando:
// - SAVINGS:accountNumber:balance:interestRate -> Create SavingsAccount, print "Account created: [accountNumber]"
// - CHECKING:accountNumber:balance:overdraftLimit -> Create CheckingAccount, print "Account created: [accountNumber]"
// - DEPOSIT:accountNumber:amount -> Deposita e imprime "Deposited $[amount] to [accountNumber]"
// - WITHDRAW:accountNumber:amount -> Withdraw and print success or "Withdrawal failed: [accountNumber]"
// - TRANSFER:fromAccount:toAccount:amount -> Transfiere e imprime éxito o "Transfer failed: [exception message]"
// - INTEREST:accountNumber -> Apply interest and print "Interest applied to [accountNumber]"
// TODO: Después de todos los comandos, imprime "--- Bank Summary ---"
// TODO: Imprime los detalles de cada cuenta usando getDetails()
// TODO: Print "Total deposits: $[total]" formatted to 2 decimal places
}
}
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 IteratorPractica por tu cuenta: Compilador de Java online