System bankowy
Część sekcji Programowanie obiektowe ścieżki Java w Coddy. Lekcja 85 z 87.
To wyzwanie polega na zbudowaniu systemu bankowego, który modeluje rzeczywiste operacje finansowe z wykorzystaniem zasad programowania obiektowego.
Twój system powinien obsługiwać różne typy kont, takie jak SavingsAccount i CheckingAccount, które rozszerzają bazową klasę Account. Każdy typ konta ma unikalne zachowania: konta oszczędnościowe mogą przynosić odsetki, a konta rozliczeniowe mogą zapewniać ochronę przed debetem.
Zastanów się, jak modelować transakcje. Interfejs taki jak Transactable mógłby definiować metody deposit() i withdraw(). Rozważ użycie własnych wyjątków, takich jak InsufficientFundsException, aby poprawnie obsługiwać nieprawidłowe operacje.
Klasa Bank może zarządzać wieloma kontami i klientami, demonstrując kompozycję. Możesz zastosować wzorzec Factory do tworzenia różnych typów kont lub użyć wzorca Observer, aby powiadamiać klientów o zmianach na kontach.
Skup się na enkapsulacji, aby chronić wrażliwe dane, takie jak salda i numery kont, oraz używaj polimorfizmu do jednolitego przetwarzania różnych typów kont.
Wyzwanie
ŁatwyZbudujmy kompletny system bankowy, który pokaże, jak dobrze opanowałeś zasady OOP! Stworzysz system z różnymi typami kont, obsługą transakcji i prawidłowym zarządzaniem wyjątkami — wszystko uporządkowane w wielu plikach.
Uporządkujesz kod w siedmiu plikach:
Transactable.java: Utwórz interfejs definiujący kontrakt dla operacji finansowych. Powinien deklarować metodydeposit(double amount)iwithdraw(double amount), zwracające wartość logiczną informującą o powodzeniu operacji.InsufficientFundsException.java: Utwórz własny wyjątek rozszerzającyException. Konstruktor powinien przyjmować kwotę próby wypłaty i bieżące saldo, tworząc komunikat w formacieInsufficient funds: attempted [amount], available [balance].Account.java: Utwórz abstrakcyjną klasę bazową reprezentującą dowolne konto bankowe. Uwzględnij prywatne polaaccountNumber(String) ibalance(double), konstruktor inicjalizujący oba pola, odpowiednie metody pobierające, chronioną metodę ustawiającą saldo (aby podklasy mogły je modyfikować) oraz metodę abstrakcyjnągetAccountType(), która zwraca String. Zaimplementuj metodęgetDetails(), która zwraca"[accountNumber] ([accountType]): $[balance]", z saldem sformatowanym do 2 miejsc po przecinku.SavingsAccount.java: Utwórz klasę rozszerzającąAccounti implementującąTransactable. Dodaj prywatne poleinterestRate(double). Konstruktor przyjmuje accountNumber, saldo początkowe i interestRate. ZaimplementujgetAccountType(), aby zwracała"Savings". W przypadkudeposit()dodaj kwotę do salda i zwróć true. W przypadkuwithdraw(), jeśli kwota przekracza saldo, zwróć false; w przeciwnym razie odejmij ją i zwróć true. Dodaj metodęapplyInterest(), która zwiększa saldo obalance * interestRate(stopa jest przechowywana jako ułamek, więc0.05oznacza 5%).CheckingAccount.java: Utwórz klasę rozszerzającąAccounti implementującąTransactable. Dodaj prywatne poleoverdraftLimit(double). Konstruktor przyjmuje accountNumber, saldo początkowe i overdraftLimit. ZaimplementujgetAccountType(), aby zwracała"Checking". W przypadkudeposit()dodaj kwotę i zwróć true. W przypadkuwithdraw()zezwól na wypłatę, jeśli kwota jest mniejsza lub równa sumie salda i overdraftLimit; zwróć false, jeśli przekracza ten limit.Bank.java: Utwórz klasę zarządzającą kontami za pomocą ArrayList. Uwzględnij metody:addAccount(Account account)— dodaje konto do bankufindAccount(String accountNumber)— zwraca Account lub null, jeśli konto nie zostało znalezionetransfer(String fromAccount, String toAccount, double amount)— przelewa pieniądze między kontami, zgłaszającInsufficientFundsException, jeśli na koncie źródłowym brakuje środków. W przypadku powodzenia zwraca"Transferred $[amount] from [fromAccount] to [toAccount]"getTotalDeposits()— zwraca sumę sald wszystkich kont
Main.java: Zbuduj swój system bankowy! Otrzymasz ciąg poleceń rozdzielonych przecinkami:SAVINGS:accountNumber:balance:interestRateCHECKING:accountNumber:balance:overdraftLimitDEPOSIT:accountNumber:amountWITHDRAW:accountNumber:amountTRANSFER:fromAccount:toAccount:amountINTEREST:accountNumber
Przetwórz każde polecenie i wypisz:
- SAVINGS/CHECKING:
Account created: [accountNumber] - DEPOSIT:
Deposited $[amount] to [accountNumber] - WITHDRAW:
Withdrew $[amount] from [accountNumber]w przypadku powodzenia lubWithdrawal failed: [accountNumber] - TRANSFER: Wypisz komunikat o powodzeniu lub
Transfer failed: [exception message] - INTEREST:
Interest applied to [accountNumber]
Po przetworzeniu wszystkich poleceń wypisz
--- Bank Summary ---, a następnie szczegóły każdego konta (za pomocągetDetails()) i na końcuTotal deposits: $[total], sformatowane do 2 miejsc po przecinku.
Otrzymasz jedno wejście: ciąg poleceń rozdzielonych przecinkami.
Na przykład dla wejścia 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 wynikiem będzie:
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.50Zwróć uwagę, że konto rozliczeniowe pozwala wypłacić $600, mimo że saldo wynosi tylko $500 — właśnie tak działa ochrona przed debetem! Konto oszczędnościowe zyskuje 5% odsetek od salda po wykonaniu przelewu. To wyzwanie łączy dziedziczenie, interfejsy, polimorfizm, własne wyjątki i hermetyzację w realistycznej aplikacji bankowej!
Spróbuj swoich sił
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
// TODO: Utwórz instancję Bank
// TODO: Podziel input według przecinków, aby uzyskać poszczególne polecenia
// TODO: Przetwórz każde polecenie:
// - SAVINGS:accountNumber:balance:interestRate -> Utwórz SavingsAccount i wypisz "Account created: [accountNumber]"
// - CHECKING:accountNumber:balance:overdraftLimit -> Utwórz CheckingAccount i wypisz "Account created: [accountNumber]"
// - DEPOSIT:accountNumber:amount -> Wpłać środki i wypisz "Deposited $[amount] to [accountNumber]"
// - WITHDRAW:accountNumber:amount -> Wypłać środki i wypisz komunikat o powodzeniu lub "Withdrawal failed: [accountNumber]"
// - TRANSFER:fromAccount:toAccount:amount -> Wykonaj przelew i wypisz komunikat o powodzeniu lub "Transfer failed: [exception message]"
// - INTEREST:accountNumber -> Nalicz odsetki i wypisz "Interest applied to [accountNumber]"
// TODO: Po przetworzeniu wszystkich poleceń wypisz "--- Bank Summary ---"
// TODO: Wypisz szczegóły każdego konta za pomocą getDetails()
// TODO: Wypisz "Total deposits: $[total]", formatując kwotę do 2 miejsc po przecinku
}
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe thisMetodyPola (atrybuty)Metoda konstruktoraPrzeciążanie konstruktoraPodsumowanie — prosty kalkulator4Dziedziczenie
Podstawy dziedziczenia (extends)Słowo kluczowe superPrzesłanianie metod (@Override)Łańcuch wywołań konstruktorówKlasa ObjectDziedziczenie jedno- i wielopoziomoweDlaczego Java nie obsługuje wielodziedziczenia klasPodsumowanie – hierarchia pracowników7Metody specjalne i klasa Object
Metoda toString()equals() i hashCode()Metoda clone()compareTo() i ComparableInterfejs ComparatorPodsumowanie — własne sortowanie10Obsługa wyjątków w programowaniu obiektowym
Hierarchia klas wyjątkówWłasne wyjątkiBłędy sprawdzane a niesprawdzaneWzorzec try-with-resourcesPodsumowanie – zweryfikowany użytkownik2Modyfikatory dostępu i enkapsulacja
Przegląd poziomów dostępuMetody pobierające i ustawiająceUkrywanie informacjiSłowo kluczowe finalPodsumowanie — menedżer kont bankowych5Polimorfizm
Podstawy przeciążania metodPrzesłanianie metod (w czasie wykonywania)Rzutowanie w górę i w dółOperator instanceofKlasy i metody abstrakcyjnePowtórka — kalkulator figur8Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieAgregacja a kompozycjaKlasy wewnętrzne, zagnieżdżone i anonimoweEnumy i metody enumówRekordy (Java 16+)Klasy zapieczętowane (Java 17+)11Wzorce projektowe — część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec BuilderWzorzec ObserverWzorzec Strategy14Końcowe wyzwania
Platforma e-learningowaSystem bankowyTworzenie postaci do gryWypożyczalnia pojazdów3Właściwości klas i składowe statyczne
Zmienne instancji a zmienne statyczneMetody statyczneBloki statyczneStałe (static final)Powtórka – Counter i Utility6Interfejsy i klasy abstrakcyjne
Wprowadzenie do interfejsówImplementowanie interfejsówImplementacja wielu interfejsówMetody domyślne i statyczne w interfejsieKlasy abstrakcyjne a interfejsyInterfejsy funkcyjnePodsumowanie — system płatnościPoćwicz samodzielnie: Kompilator Java online