Menu
Coddy logo textTech

銀行システム

CoddyのJavaジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 85/87。

このチャレンジでは、OOP(オブジェクト指向プログラミング)の原則を使用して現実世界の金融業務をモデル化する銀行システムの構築に取り組んでいただきます。

システムは、SavingsAccountCheckingAccount のような異なる口座タイプを処理する必要があります。これらは両方ともベースの Account クラスを継承します。各口座タイプには独自の動作があります。例えば、普通預金口座は利息が発生する場合があり、当座預金口座は当座貸越保護を持つ場合があります。

トランザクションをどのようにモデル化するか考えてみましょう。Transactable のようなインターフェースで、deposit()withdraw() のメソッドを定義できます。無効な操作を適切に処理するために、InsufficientFundsException などのカスタム例外の使用を検討してください。

Bankクラスは、複数の口座や顧客を管理し、コンポジション(合成)を実証する場合があります。Factoryパターンを適用して異なる口座タイプを作成したり、Observerパターンを使用して口座の変更を顧客に通知したりすることができます。

残高や口座番号などの機密データを保護するためにカプセル化を重視し、異なる口座タイプを統一的に処理するためにポリモーフィズムを使用します。

challenge icon

チャレンジ

簡単

OOPの原則をマスターしていることを証明する、完全な銀行システムを構築しましょう!異なる口座タイプ、取引処理、適切な例外管理を備えたシステムを、複数のファイルに分けて作成します。

コードは以下の7つのファイルに分けて構成します:

  • Transactable.java: 金融操作のコントラクトを定義するインターフェースを作成します。deposit(double amount)withdraw(double amount) メソッドを宣言し、どちらも成功を示す boolean を返すようにします。
  • InsufficientFundsException.java: Exception を継承したカスタム例外を作成します。コンストラクタは試行された引き出し額と現在の残高を受け取り、Insufficient funds: attempted [amount], available [balance] という形式のメッセージを作成する必要があります。
  • Account.java: 任意の銀行口座を表す抽象基底クラスを作成します。accountNumber (String) と balance (double) のプライベートフィールド、両方を初期化するコンストラクタ、適切なゲッター、サブクラスが変更できるように balance の protected セッター、および String を返す抽象メソッド getAccountType() を含めます。"[accountNumber] ([accountType]): $[balance]" を返し、残高を小数点以下2桁にフォーマットする getDetails() メソッドを実装します。
  • SavingsAccount.java: Account を継承し、Transactable を実装するクラスを作成します。interestRate (double) のプライベートフィールドを追加します。コンストラクタは accountNumber、初期残高、および interestRate を受け取ります。getAccountType() を実装して "Savings" を返すようにします。deposit() では、金額を残高に加え、true を返します。withdraw() では、金額が残高を超える場合は false を返し、それ以外の場合は差し引いて true を返します。残高を balance * interestRate だけ増加させる applyInterest() メソッドを追加します(利率は小数として保存されるため、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) - 口座を返すか、見つからない場合は null を返します
    • transfer(String fromAccount, String toAccount, double amount) - 口座間で送金を行い、元の口座の残高が不足している場合は InsufficientFundsException をスローします。成功した場合は、"Transferred $[amount] from [fromAccount] to [toAccount]" を返します
    • 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 $[amount] to [accountNumber]
    • WITHDRAW: 成功時は Withdrew $[amount] from [accountNumber]、失敗時は Withdrawal failed: [accountNumber]
    • TRANSFER: 成功メッセージ、または Transfer failed: [exception message] を出力します
    • INTEREST: Interest applied to [accountNumber]

    すべてのコマンドの後、--- Bank Summary --- を出力し、続いて各口座の詳細(getDetails() を使用)を出力し、最後に小数点以下2桁にフォーマットされた Total deposits: $[total] を出力します。

入力として、カンマ区切りのコマンド文字列を1つ受け取ります。

例えば、入力が 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

当座預金口座(Checking account)が、残高が $500 しかないにもかかわらず $600 の引き出しを許可していることに注目してください。これがオーバードラフト保護(当座貸越保護)の機能です!普通預金口座(Savings account)は、送金後の残高に対して 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: 小数点以下2桁にフォーマットされた "Total deposits: $[total]" を出力する
    }
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン