Menu
Coddy logo textTech

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.

challenge icon

Desafío

Fácil

¡Vamos a construir un Sistema Bancario completo que demuestre tu dominio de los principios de la POO! Crearás un sistema con diferentes tipos de cuentas, 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étodos deposit(double amount) y withdraw(double amount), ambos devolviendo un booleano para indicar el éxito.
  • InsufficientFundsException.java: Crea una excepción personalizada que extienda de Exception. 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 para accountNumber (String) y balance (double), un constructor que inicialice ambos, los getters apropiados, un setter protegido para balance (para que las subclases puedan modificarlo) y un método abstracto getAccountType() que devuelva un String. Implementa un método getDetails() que devuelva "%s (%s): $%.2f" con el saldo formateado a 2 decimales.
  • SavingsAccount.java: Crea una clase que extienda de Account e implemente Transactable. Añade un campo privado para interestRate (double). El constructor recibe accountNumber, saldo inicial e interestRate. Implementa getAccountType() para que devuelva "Savings". Para deposit(), añade el monto al saldo y devuelve true. Para withdraw(), si el monto excede el saldo, devuelve false; de lo contrario, réstalo y devuelve true. Añade un método applyInterest() que aumente el saldo según el porcentaje de la tasa de interés.
  • CheckingAccount.java: Crea una clase que extienda de Account e implemente Transactable. Añade un campo privado para overdraftLimit (double). El constructor recibe accountNumber, saldo inicial y overdraftLimit. Implementa getAccountType() para que devuelva "Checking". Para deposit(), añade el monto y devuelve true. Para withdraw(), permite el retiro si el monto es menor o igual al saldo más el 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 banco
    • findAccount(String accountNumber) - devuelve la Account o null si no se encuentra
    • transfer(String fromAccount, String toAccount, double amount) - transfiere dinero entre cuentas, lanzando InsufficientFundsException si 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 (usando getDetails()) 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!

Hoja de referencia

Un Sistema Bancario demuestra los principios de la POO a través de la gestión de cuentas, transacciones y el manejo de excepciones.

Interfaces para Contratos

Define operaciones comunes utilizando interfaces:

public interface Transactable {
    boolean deposit(double amount);
    boolean withdraw(double amount);
}

Excepciones Personalizadas

Crea excepciones personalizadas para errores específicos del dominio:

public class InsufficientFundsException extends Exception {
    public InsufficientFundsException(double attempted, double available) {
        super("Insufficient funds: attempted " + attempted + ", available " + available);
    }
}

Clases Base Abstractas

Utiliza clases abstractas para definir una estructura común con métodos abstractos para el comportamiento específico de las subclases:

public abstract class Account {
    private String accountNumber;
    private double balance;
    
    public abstract String getAccountType();
    
    protected void setBalance(double balance) {
        this.balance = balance;
    }
}

Herencia y Polimorfismo

Las subclases extienden las clases base e implementan interfaces:

public class SavingsAccount extends Account implements Transactable {
    private double interestRate;
    
    @Override
    public String getAccountType() {
        return "Savings";
    }
    
    public void applyInterest() {
        setBalance(getBalance() * (1 + interestRate));
    }
}

Composición

Las clases pueden gestionar colecciones de otros objetos:

public class Bank {
    private ArrayList<Account> accounts;
    
    public void addAccount(Account account) {
        accounts.add(account);
    }
    
    public Account findAccount(String accountNumber) {
        // Buscar y devolver la cuenta o null
    }
}

Encapsulación

Protege los datos sensibles con campos privados y acceso controlado a través de getters/setters. Utiliza modificadores protected para permitir el acceso a las subclases manteniendo la encapsulación.

Manejo de Excepciones en Transacciones

Lanza excepciones personalizadas para operaciones no válidas:

public String transfer(String from, String to, double amount) throws InsufficientFundsException {
    if (!fromAccount.withdraw(amount)) {
        throw new InsufficientFundsException(amount, fromAccount.getBalance());
    }
    toAccount.deposit(amount);
    return "Transferred $" + amount;
}

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 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]" formateado a 2 decimales
    }
}
quiz iconPonte a prueba

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