Menu
Coddy logo textTech

Банковская система

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 85 из 87.

В рамках этого испытания вам предстоит создать Банковскую систему, которая моделирует реальные финансовые операции, используя принципы ООП.

Ваша система должна поддерживать различные типы счетов, такие как SavingsAccount и CheckingAccount, оба из которых расширяют базовый класс Account. Каждый тип счета обладает уникальным поведением: сберегательные счета могут приносить проценты, в то время как текущие счета могут иметь защиту от овердрафта.

Подумайте о том, как моделировать транзакции. Интерфейс, такой как Transactable, мог бы определять методы для deposit() и withdraw(). Рассмотрите возможность использования пользовательских исключений, таких как InsufficientFundsException, для корректной обработки недопустимых операций.

Класс Bank может управлять несколькими счетами и клиентами, демонстрируя композицию. Вы могли бы применить паттерн Factory для создания различных типов счетов или использовать паттерн Observer для уведомления клиентов об изменениях в счете.

Сосредоточьтесь на инкапсуляции для защиты конфиденциальных данных, таких как балансы и номера счетов, и используйте полиморфизм для единообразной обработки различных типов счетов.

challenge icon

Задание

Легко

Давайте создадим полноценную банковскую систему, которая продемонстрирует ваше мастерство в принципах ООП! Вы создадите систему с различными типами счетов, обработкой транзакций и правильным управлением исключениями — и все это будет организовано в нескольких файлах.

Вы организуете свой код в семи файлах:

  • Transactable.java: Создайте интерфейс, который определяет контракт для финансовых операций. Он должен объявлять методы deposit(double amount) и withdraw(double amount), оба возвращают логическое значение для индикации успеха.
  • InsufficientFundsException.java: Создайте пользовательское исключение, которое расширяет Exception. Конструктор должен принимать сумму попытки снятия и текущий баланс, создавая сообщение в формате "Insufficient funds: attempted %.2f, available %.2f".
  • Account.java: Создайте абстрактный базовый класс, представляющий любой банковский счет. Включите приватные поля для accountNumber (String) и balance (double), конструктор, который инициализирует оба поля, соответствующие геттеры, защищенный (protected) сеттер для баланса (чтобы подклассы могли его изменять) и абстрактный метод getAccountType(), который возвращает String. Реализуйте метод getDetails(), который возвращает "%s (%s): $%.2f", где баланс отформатирован до 2 знаков после запятой.
  • SavingsAccount.java: Создайте класс, который расширяет Account и реализует Transactable. Добавьте приватное поле для interestRate (double). Конструктор принимает accountNumber, начальный баланс и interestRate. Реализуйте getAccountType(), чтобы он возвращал "Savings". Для deposit() добавьте сумму к балансу и верните true. Для withdraw(), если сумма превышает баланс, верните false; в противном случае вычтите сумму и верните true. Добавьте метод applyInterest(), который увеличивает баланс на balance * interestRate (ставка хранится как дробь, поэтому 0.05 означает 5%).
  • CheckingAccount.java: Создайте класс, который расширяет Account и реализует Transactable. Добавьте приватное поле для overdraftLimit (double). Конструктор принимает accountNumber, начальный баланс и overdraftLimit. Реализуйте getAccountType(), чтобы он возвращал "Checking". Для deposit() добавьте сумму и верните true. Для withdraw() разрешите снятие, если сумма меньше или равна балансу плюс overdraftLimit; верните false, если она превышает этот лимит.
  • Bank.java: Создайте класс, который управляет счетами с помощью ArrayList. Включите методы:
    • addAccount(Account account) - добавляет счет в банк
    • findAccount(String accountNumber) - возвращает Account или null, если счет не найден
    • transfer(String fromAccount, String toAccount, double amount) - переводит деньги между счетами, выбрасывая InsufficientFundsException, если на исходном счете недостаточно средств. При успехе возвращает "Transferred $%.2f from %s to %s"
    • getTotalDeposits() - возвращает сумму балансов всех счетов
  • Main.java: Постройте свою банковскую систему! Вы получите строку команд, разделенных запятыми:
    • SAVINGS:accountNumber:balance:interestRate
    • CHECKING:accountNumber:balance:overdraftLimit
    • DEPOSIT:accountNumber:amount
    • WITHDRAW:accountNumber:amount
    • TRANSFER:fromAccount:toAccount:amount
    • INTEREST:accountNumber

    Обработайте каждую команду и выведите:

    • SAVINGS/CHECKING: "Account created: " + accountNumber
    • DEPOSIT: "Deposited $%.2f to %s%n"
    • WITHDRAW: "Withdrew $%.2f from %s%n" при успехе или "Withdrawal failed: " + accountNumber
    • TRANSFER: Выведите сообщение об успехе или "Transfer failed: " + e.getMessage()
    • INTEREST: "Interest applied to " + accountNumber

    После всех команд выведите "--- Bank Summary ---", затем детали каждого счета (используя getDetails()) и, наконец, "Total deposits: $%.2f%n", отформатированные до 2 знаков после запятой.

Вы получите один входной параметр: строку команд, разделенных запятыми.

Например, при входных данных 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 ваш вывод будет таким:

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

Обратите внимание, как чековый счет позволяет снять 600 долларов, несмотря на то, что на балансе всего 500 долларов — это работа защиты от овердрафта! Сберегательный счет получает 5% годовых на свой баланс после перевода. Эта задача объединяет наследование, интерфейсы, полиморфизм, пользовательские исключения и инкапсуляцию в реалистичное банковское приложение!

Попробуйте сами

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        
        // TODO: Создайте экземпляр Bank
        
        // TODO: Разделите входную строку по запятой, чтобы получить отдельные команды
        
        // TODO: Обработайте каждую команду:
        // - SAVINGS:accountNumber:balance:interestRate -> Создайте SavingsAccount, выведите "Account created: [accountNumber]"
        // - CHECKING:accountNumber:balance:overdraftLimit -> Создайте CheckingAccount, выведите "Account created: [accountNumber]"
        // - DEPOSIT:accountNumber:amount -> Внесите депозит и выведите "Deposited $[amount] to [accountNumber]"
        // - WITHDRAW:accountNumber:amount -> Снимите средства и выведите сообщение об успехе или "Withdrawal failed: [accountNumber]"
        // - TRANSFER:fromAccount:toAccount:amount -> Выполните перевод и выведите сообщение об успехе или "Transfer failed: [exception message]"
        // - INTEREST:accountNumber -> Примените проценты и выведите "Interest applied to [accountNumber]"
        
        // TODO: После всех команд выведите "--- Bank Summary ---"
        
        // TODO: Выведите детали каждого счета, используя getDetails()
        
        // TODO: Выведите "Total deposits: $[total]", отформатировав до 2 знаков после запятой
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование