نظام مصرفي
جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 104 من 104.
التحدي
سهللنقم ببناء نظام بنكي يوضح نمط الحالة (State pattern)، والوراثة، وإدارة المؤشرات الذكية (smart pointers). ستقوم بإنشاء نظام يمكن أن تكون فيه الحسابات في حالات مختلفة (Active، Frozen، Closed)، ولكل منها سلوكيات متميزة للتعامل مع المعاملات.
ستقوم بتنظيم الكود الخاص بك عبر ستة ملفات:
AccountState.h: تحديد البنية التحتية لنمط الحالة لحالات الحساب.أنشئ فئة أساسية مجردة
AccountStateمع دوال افتراضية بحتة (pure virtual methods):deposit(double amount)— تعيد true إذا كان الإيداع مسموحاً به، و false خلاف ذلكwithdraw(double amount)— تعيد true إذا كان السحب مسموحاً به، و false خلاف ذلكgetStateName()— تعيد اسم الحالة كسلسلة نصية (string)
قم بتنفيذ ثلاث حالات ملموسة (concrete states):
ActiveState: تسمح بكل من الإيداعات والسحوبات، وتعيد"Active"FrozenState: تسمح بالإيداعات ولكنها ترفض السحوبات، وتعيد"Frozen"ClosedState: ترفض كل من الإيداعات والسحوبات، وتعيد"Closed"
Account.h: بناء هيكل هرمي للحساب مع إدارة الحالة.أنشئ فئة أساسية
Accountتحتوي على:- رقم الحساب (string)، واسم المالك، والرصيد
std::unique_ptr<AccountState>لإدارة الحالة الحاليةdeposit(double amount)— تتحقق من الحالة أولاً، إذا كان مسموحاً تضيف إلى الرصيد وتطبع"Deposited [amount] to [accountNumber]"، وإلا تطبع"Deposit rejected: account is [stateName]"withdraw(double amount)— تتحقق من الحالة، إذا كان مسموحاً وكان هناك رصيد كافٍ، تخصم وتطبع"Withdrew [amount] from [accountNumber]". إذا رفضت الحالة، تطبع"Withdrawal rejected: account is [stateName]". إذا كان الرصيد غير كافٍ، تطبع"Insufficient funds"freeze()وactivate()وclose()— تغيير حالة الحسابgetInfo()— تعيد"[accountNumber] ([ownerName]): $[balance] - [stateName]"- دالة افتراضية
getAccountType()تعيد"Basic"
أنشئ نوعين من الحسابات المشتقة:
SavingsAccount: لديه متطلب حد أدنى للرصيد (يتم تمريره للمنشئ). قم بإعادة تعريف (override) دالة withdraw للتحقق أيضاً مما إذا كان السحب سيجعل الرصيد أقل من الحد الأدنى — إذا كان الأمر كذلك، اطبع"Cannot go below minimum balance of [minimum]". تعيد"Savings"لنوع الحساب.CheckingAccount: لديه حد للسحب المكشوف (overdraft limit) (يتم تمريره للمنشئ). يسمح بالسحوبات حتى (balance + overdraftLimit). تعيد"Checking"لنوع الحساب.
Transaction.h: نمذجة المعاملات ككائنات.أنشئ فئة
Transactionتسجل:- نوع المعاملة (string: "Deposit", "Withdrawal", "Transfer")
- المبلغ
- رقم الحساب المعني
- حالة النجاح (bool)
أضف دالة
getDescription()تعيد"[type]: $[amount] on [accountNumber] - [Success/Failed]"Customer.h: إنشاء عميل يمتلك حسابات متعددة.العميل
Customerلديه اسم، ومعرف (ID)، و vector منstd::shared_ptr<Account>. قم بتنفيذ:addAccount(std::shared_ptr<Account> account)getAccount(const std::string& accountNumber)— يعيد الحساب المطابق أو nullptrgetTotalBalance()— يجمع الأرصدة عبر جميع الحساباتlistAccounts()— يطبع معلومات كل حساب
Bank.h: تنسيق العمليات البنكية.تقوم فئة
Bankبتخزين العملاء والاحتفاظ بسجل المعاملات. قم بتنفيذ:addCustomer(std::shared_ptr<Customer> customer)findAccount(const std::string& accountNumber)— يبحث في جميع العملاء عن الحسابprocessDeposit(const std::string& accountNumber, double amount)— يجد الحساب، ينفذ الإيداع، ويسجل المعاملةprocessWithdrawal(const std::string& accountNumber, double amount)— يجد الحساب، ينفذ السحب، ويسجل المعاملةgetTransactionCount()— يعيد إجمالي المعاملات التي تمت معالجتها
main.cpp: عرض نظامك البنكي.اقرأ أربعة مدخلات:
- تفاصيل العميل (تنسيق:
name,customerId) - تفاصيل حساب التوفير (تنسيق:
accountNumber,minBalance) - العملية 1 (تنسيق:
action,accountNumber,amountحيث action هوdepositأوwithdraw) - العملية 2 (تنسيق:
action,accountNumber,amountأوfreeze,accountNumber)
أنشئ البنك والعميل. أنشئ حساب توفير مع العميل كمالك وأضفه إلى العميل. أضف العميل إلى البنك. قم بمعالجة كلتا العمليتين (إذا كان أمر تجميد freeze، فقم بتجميد الحساب ثم حاول إجراء سحب صغير بقيمة $10 لتوضيح الحالة). أخيراً، اطبع قائمة حسابات العميل وإجمالي عدد المعاملات كـ
"Transactions: [count]".- تفاصيل العميل (تنسيق:
على سبيل المثال، مع المدخلات Alice,C001، و SAV001,100، و deposit,SAV001,500، و withdraw,SAV001,200:
Deposited 500 to SAV001
Withdrew 200 from SAV001
SAV001 (Alice): $300 - Active
Transactions: 2مع المدخلات Bob,C002، و SAV002,50، و deposit,SAV002,100، و freeze,SAV002:
Deposited 100 to SAV002
Withdrawal rejected: account is Frozen
SAV002 (Bob): $100 - Frozen
Transactions: 2مع المدخلات Carol,C003، و SAV003,200، و deposit,SAV003,250، و withdraw,SAV003,100:
Deposited 250 to SAV003
Cannot go below minimum balance of 200
SAV003 (Carol): $250 - Active
Transactions: 2يجمع هذا التحدي بين نمط الحالة لإدارة سلوكيات الحساب، والوراثة لأنواع الحسابات المختلفة، والمؤشرات الذكية لعلاقات الملكية، وتتبع المعاملات — وهي جميعها مفاهيم أساسية أتقنتها طوال هذه الدورة.
جرّب بنفسك
#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include "Bank.h"
int main() {
// قراءة المدخل 1: تفاصيل العميل (التنسيق: name,customerId)
std::string customerInput;
std::getline(std::cin, customerInput);
// قراءة المدخل 2: تفاصيل حساب التوفير (التنسيق: accountNumber,minBalance)
std::string accountInput;
std::getline(std::cin, accountInput);
// قراءة المدخل 3: العملية 1 (التنسيق: action,accountNumber,amount)
std::string op1Input;
std::getline(std::cin, op1Input);
// قراءة المدخل 4: العملية 2 (التنسيق: action,accountNumber,amount أو freeze,accountNumber)
std::string op2Input;
std::getline(std::cin, op2Input);
// TODO: تحليل تفاصيل العميل من customerInput
// تلميح: استخدم find(',') لتقسيم السلسلة النصية
// TODO: تحليل تفاصيل الحساب من accountInput
// TODO: إنشاء البنك
// TODO: إنشاء العميل
// TODO: إنشاء حساب توفير مع تعيين العميل كمالك له
// TODO: إضافة الحساب إلى العميل
// TODO: إضافة العميل إلى البنك
// TODO: تحليل ومعالجة العملية 1
// التنسيق: action,accountNumber,amount (الـ action هو "deposit" أو "withdraw")
// TODO: تحليل ومعالجة العملية 2
// يمكن أن تكون: action,accountNumber,amount أو freeze,accountNumber
// في حال freeze، قم بتجميد الحساب ثم حاول سحب مبلغ $10
// TODO: طباعة قائمة حسابات العميل
// TODO: طباعة عدد العمليات بصيغة "Transactions: [count]"
return 0;
}
جميع دروس Object Oriented Programming
1أساسيات الـ OOP
الملفات الخارجيةبناء وتجميع (Compilation) لغة C++ملفات الـ Header وملفات الـ Sourceالـ Namespaces والـ Scopeمقدمة في الـ OOP في C++الـ Classes مقابل الـ Objectsالمؤشر 'this'الـ Methods (الدوال الأعضاء)الـ Attributes (بيانات الأعضاء)أساسيات الـ Ctors والـ Dtorsمراجعة - آلة حاسبة بسيطة4خصائص الـ Class
أعضاء الـ Instance مقابل الـ Staticدوال الـ Getters والـ Settersدوال الأعضاء الثابتة (Const)الكلمة المفتاحية Mutableالدوال والمتغيرات الساكنة (Static)الدوال والفئات الصديقة (Friend)مراجعة - مدير الحساب البنكي7الوراثة
الوراثة الأساسيةمستويات الوصول في الوراثةترتيب استدعاء الـ Ctor والـ Dtorإعادة تعريف الدوال (Method Overriding)الدوال الافتراضية والـ VTableالوراثة المتعددةالوراثة الافتراضيةمراجعة - هيكلية الموظفين10نظرة عامة على STL
نظرة عامة وفلسفة STLحاويات STLالـ Iteratorsخوارزميات STLالـ Functors وتعبيرات Lambdaمراجعة - تكرار الكلمات13أنماط التصميم - الجزء الأول
مقدمة في أنماط التصميمنمط Singletonنمط Factory و Abstract Factoryنمط Builderنمط Observerنمط Strategy2إدارة الذاكرة
ذاكرة Stack مقابل Heapالمؤشرات والمراجعالذاكرة الديناميكية (new/delete)المؤشرات الذكية في C++RAII في C++مراجعة - مدير المصفوفات الديناميكية5التغليف (Encapsulation)
محددات الوصول في C++محددات الوصول بشكل متعمقإخفاء المعلوماتStruct مقابل Classالأصناف المتداخلة والداخليةمراجعة - نظام سجلات الطلاب8تعدد الأشكال (Polymorphism)
تعدد الأشكال: وقت التجميع مقابل وقت التشغيلالتحميل الزائد للدوال (Function Overloading)مراجعة الدوال الافتراضية (Virtual Functions)الدوال الافتراضية البحتة (Pure Virtual Functions)الأصناف المجردة (Abstract Classes)تصميم الواجهات (Interface) في C++التحويل الديناميكي (Dynamic Casting) و RTTIملخص - حاسبة الأشكال11مفاهيم OOP المتقدمة
التركيب مقابل الوراثةالـ Mixins عبر CRTPنمط Pimplمحو النوع (Type Erasure)أصناف Enum والأنواع القويةمعالجة الاستثناءات في OOPتسلسلات الاستثناءات المخصصة14أنماط التصميم - الجزء الثاني
نمط الأمرنمط المحولنمط المزيننمط قالب الطريقةنمط الحالةنمط التركيبRAII كنمط3المنشئات والموادم
المنشئ الافتراضيالمنشئ ذو المعاملاتمنشئ النسخمنشئ النقلقوائم تهيئة المنشئالمنشئات المفوضةتعمق في الموادمقاعدة الثلاثة / الخمسة / الصفرمراجعة - فئة String6تحميل العوامل (Operator Overloading)
مقدمة في تحميل العواملتحميل العوامل الحسابيةتحميل عوامل المقارنةعوامل Streamتحميل عامل التعيينتحميل العوامل [] و ()عوامل تحويل النوعمراجعة - Matrix Class9القوالب
قوالب الدوالقوالب الأصنافتخصيص القوالبالقوالب المتغيرةأساسيات SFINAE و Type Traitsمراجعة - الحاويات العامة