Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

النظام المصرفي

جزء من قسم البرمجة كائنية التوجه في رحلة Java على Coddy. الدرس 85 من 87.

يتحدّاك هذا التمرين ببناء نظام مصرفي يحاكي العمليات المالية في العالم الحقيقي باستخدام مبادئ البرمجة كائنية التوجه.

يجب أن يتعامل نظامك مع أنواع مختلفة من الحسابات مثل SavingsAccount وCheckingAccount، وكلاهما يمتد من فئة أساسية هي Account. لكل نوع من الحسابات سلوكيات فريدة: فقد تكسب حسابات التوفير فائدة، بينما قد تتمتع الحسابات الجارية بحماية من السحب على المكشوف.

فكّر في كيفية نمذجة المعاملات. يمكن لواجهة مثل Transactable أن تحدّد أساليب لـ deposit() وwithdraw(). فكّر في استخدام استثناءات مخصّصة مثل InsufficientFundsException لمعالجة العمليات غير الصالحة بسلاسة.

قد تدير فئة Bank حسابات وعملاء متعدّدين، موضّحةً مفهوم التركيب. يمكنك تطبيق نمط Factory لإنشاء أنواع مختلفة من الحسابات، أو استخدام نمط Observer لإخطار العملاء بتغييرات الحساب.

ركّز على التغليف لحماية البيانات الحساسة مثل balances وأرقام account، واستخدم تعدد الأشكال لمعالجة أنواع account المختلفة بشكل موحّد.

challenge icon

التحدي

سهل

لنبنِ نظامًا مصرفيًا متكاملًا يبرهن على إتقانك لمبادئ البرمجة كائنية التوجه! ستنشئ نظامًا يتضمن أنواعًا مختلفة من الحسابات، ومعالجة المعاملات، وإدارة الاستثناءات بطريقة صحيحة، وكل ذلك منظّم عبر ملفات متعددة.

ستنظّم شيفرتك عبر سبعة ملفات:

  • Transactable.java: أنشئ واجهة تحدد العقد الخاص بالعمليات المالية. يجب أن تعلن عن الطريقتين deposit(double amount) وwithdraw(double amount)، وكلتاهما تعيدان قيمة منطقية للإشارة إلى النجاح.
  • InsufficientFundsException.java: أنشئ استثناءً مخصصًا يمتد من Exception. يجب أن يستقبل المُنشئ مبلغ السحب attempted والرصيد الحالي، وأن ينشئ رسالة بالتنسيق Insufficient funds: attempted [amount], available [balance].
  • Account.java: أنشئ فئة أساسية مجردة تمثل أي حساب مصرفي. أدرج حقولًا خاصة لـ accountNumber من النوع String وbalance من النوع double، ومُنشئًا يهيّئ كليهما، وواحدات وصول مناسبة، وsetter محميًا للـ balance (حتى تتمكن الفئات الفرعية من تعديله)، وطريقة مجردة getAccountType() تعيد قيمة من النوع String. نفّذ طريقة getDetails() التي تعيد "[accountNumber] ([accountType]): $[balance]" مع تنسيق balance ليظهر حتى منزلتين عشريتين.
  • SavingsAccount.java: أنشئ فئة تمتد من Account وتنفّذ Transactable. أضف حقلًا خاصًا لـ interestRate من النوع double. يستقبل المُنشئ accountNumber وbalance الابتدائي وinterestRate. نفّذ getAccountType() لتعيد "Savings". بالنسبة إلى deposit()، أضف المبلغ إلى balance وأعد true. وبالنسبة إلى withdraw()، إذا تجاوز المبلغ balance فأعد false؛ وإلا اطرح المبلغ وأعد true. أضف طريقة applyInterest() تزيد balance بمقدار balance * interestRate (يُخزَّن المعدل على شكل كسر، لذا فإن 0.05 تعني 5%).
  • CheckingAccount.java: أنشئ فئة تمتد من Account وتنفّذ Transactable. أضف حقلًا خاصًا لـ overdraftLimit من النوع double. يستقبل المُنشئ accountNumber وbalance الابتدائي وoverdraftLimit. نفّذ getAccountType() لتعيد "Checking". بالنسبة إلى deposit()، أضف المبلغ وأعد true. وبالنسبة إلى withdraw()، اسمح بالسحب إذا كان المبلغ أقل من أو يساوي balance زائد overdraftLimit؛ وأعد false إذا تجاوز هذا الحد.
  • Bank.java: أنشئ فئة تدير الحسابات باستخدام ArrayList. أدرج الطرق التالية:
    • addAccount(Account account) - تضيف حسابًا إلى البنك
    • findAccount(String accountNumber) - تعيد Account أو 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())، وأخيرًا Total deposits: $[total] مع تنسيق القيمة حتى منزلتين عشريتين.

ستتلقى مُدخلًا واحدًا: سلسلة الأوامر المفصولة بفواصل.

على سبيل المثال، عند استخدام المُدخل 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 بسحب $600 رغم أن رصيده لا يتجاوز $500: هذه هي آلية الحماية من السحب على المكشوف! يحقق حساب Savings فائدة بنسبة 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 -> Create SavingsAccount, print "Account created: [accountNumber]"
        // - CHECKING:accountNumber:balance:overdraftLimit -> Create CheckingAccount, print "Account created: [accountNumber]"
        // - DEPOSIT:accountNumber:amount -> قم بالإيداع واطبع "Deposited $[amount] to [accountNumber]"
        // - WITHDRAW:accountNumber:amount -> Withdraw and print success or "Withdrawal failed: [accountNumber]"
        // - TRANSFER:fromAccount:toAccount:amount -> قم بالتحويل واطبع نجاح العملية أو "Transfer failed: [exception message]"
        // - INTEREST:accountNumber -> Apply interest and print "Interest applied to [accountNumber]"
        
        // TODO: بعد تنفيذ جميع الأوامر، اطبع "--- Bank Summary ---"
        
        // TODO: طباعة تفاصيل كل حساب باستخدام getDetails()
        
        // TODO: Print "Total deposits: $[total]" formatted to 2 decimal places
    }
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Java عبر الإنترنت