Банковская система
Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 85 из 87.
В рамках этого задания вам предстоит создать Банковскую систему, которая моделирует реальные финансовые операции, используя принципы ООП.
Ваша система должна обрабатывать различные типы счетов, такие как SavingsAccount и CheckingAccount, оба из которых расширяют базовый Account класс. Каждый тип счета имеет уникальное поведение: сберегательные счета могут приносить проценты, в то время как текущие счета могут иметь защиту от овердрафта.
Подумайте о том, как моделировать транзакции. Интерфейс, такой как Transactable, может определять методы для deposit() и withdraw(). Рассмотрите возможность использования пользовательских исключений, таких как InsufficientFundsException, для корректной обработки недопустимых операций.
Класс Bank может управлять несколькими счетами и клиентами, демонстрируя композицию. Вы могли бы применить паттерн Factory для создания различных типов счетов или использовать паттерн Observer для уведомления клиентов об изменениях в счете.
Сосредоточьтесь на инкапсуляции для защиты конфиденциальных данных, таких как балансы и номера счетов, и используйте полиморфизм для единообразной обработки различных типов счетов.
Задание
ЛегкоДавайте создадим полноценную банковскую систему, которая продемонстрирует ваше мастерство владения принципами ООП! Вы создадите систему с различными типами счетов, обработкой транзакций и правильным управлением исключениями — и все это будет организовано в нескольких файлах.
Вы распределите свой код по семи файлам:
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(), который увеличивает баланс на процентную ставку.CheckingAccount.java: Создайте класс, который расширяетAccountи реализуетTransactable. Добавьте приватное поле дляoverdraftLimit(double). Конструктор принимает accountNumber, начальный баланс и overdraftLimit. РеализуйтеgetAccountType(), чтобы он возвращал"Checking". Дляdeposit()добавьте сумму и верните true. Дляwithdraw()разрешите снятие, если сумма меньше или равна сумме баланса и лимита овердрафта; верните 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% годовых на свой баланс после перевода. Эта задача объединяет наследование, интерфейсы, полиморфизм, пользовательские исключения и инкапсуляцию в реалистичное банковское приложение!
Шпаргалка
Банковская система демонстрирует принципы ООП через управление счетами, транзакции и обработку исключений.
Интерфейсы для контрактов
Определите общие операции с помощью интерфейсов:
public interface Transactable {
boolean deposit(double amount);
boolean withdraw(double amount);
}Пользовательские исключения
Создавайте пользовательские исключения для ошибок, специфичных для предметной области:
public class InsufficientFundsException extends Exception {
public InsufficientFundsException(double attempted, double available) {
super("Insufficient funds: attempted " + attempted + ", available " + available);
}
}Абстрактные базовые классы
Используйте абстрактные классы для определения общей структуры с абстрактными методами для поведения, специфичного для подклассов:
public abstract class Account {
private String accountNumber;
private double balance;
public abstract String getAccountType();
protected void setBalance(double balance) {
this.balance = balance;
}
}Наследование и полиморфизм
Подклассы расширяют базовые классы и реализуют интерфейсы:
public class SavingsAccount extends Account implements Transactable {
private double interestRate;
@Override
public String getAccountType() {
return "Savings";
}
public void applyInterest() {
setBalance(getBalance() * (1 + interestRate));
}
}Композиция
Классы могут управлять коллекциями других объектов:
public class Bank {
private ArrayList<Account> accounts;
public void addAccount(Account account) {
accounts.add(account);
}
public Account findAccount(String accountNumber) {
// Поиск и возврат счета или null
}
}Инкапсуляция
Защищайте конфиденциальные данные с помощью приватных полей и контролируемого доступа через геттеры/сеттеры. Используйте модификаторы protected, чтобы разрешить доступ подклассам, сохраняя при этом инкапсуляцию.
Обработка исключений в транзакциях
Генерируйте пользовательские исключения для недопустимых операций:
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;
}Попробуйте сами
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 знаков после запятой
}
}
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово thisМетодыПоля (атрибуты)Метод-конструкторПерегрузка конструкторовИтоги — Простой калькулятор4Наследование
Основы наследования (extends)Ключевое слово superПереопределение методов (@Override)Цепочка конструкторовКласс ObjectОдиночное и многоуровневое наследованиеПочему нет множественного наследования классовИтоги — Иерархия сотрудников7Специальные методы и класс Object
Метод toString()equals() и hashCode()Метод clone()compareTo() и ComparableИнтерфейс ComparatorПовторение — Кастомная сортировка2Модификаторы доступа и инкапсуляция
Обзор уровней доступаМетоды геттеры и сеттерыСокрытие данныхКлючевое слово finalИтоги — Менеджер банковского счета5Полиморфизм
Основы перегрузки методовПереопределение методов (Run-Time)Upcasting и DowncastingОператор instanceofАбстрактные классы и методыИтоги: Калькулятор фигур8Продвинутые концепции ООП
Композиция против наследованияАгрегация против композицииВнутренние, вложенные и анонимные классыEnums и методы перечисленийRecords (Java 16+)Sealed-классы (Java 17+)11Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн BuilderПаттерн ObserverПаттерн Strategy14Финальные испытания
Платформа онлайн-обученияБанковская системаРазработка игрового персонажаСервис аренды транспорта3Свойства класса и статические члены
Переменные экземпляра и статические переменныеСтатические методыСтатические блокиКонстанты (static final)Итоги: Счетчик и утилиты6Интерфейсы и абстрактные классы
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовDefault и Static методы в интерфейсахАбстрактные классы vs ИнтерфейсыФункциональные интерфейсыИтоги — Платежная система9Обобщения
Введение в обобщенияОбобщенные классыОбобщенные методыОграниченные параметры типаСимволы подстановки (Wildcards: ?, extends, super)Итоги — Обобщенный контейнер12Паттерны проектирования. Часть 2
Паттерн «Команда»Паттерн «Адаптер»Паттерн «Декоратор»Паттерн «Шаблонный метод»Паттерн «Состояние»Паттерн «Компоновщик»Паттерн «Итератор»