نظام مصرفي
جزء من قسم البرمجة كائنية التوجه في رحلة C++ على Coddy. الدرس 104 من 104.
التحدي
سهللنَبْنِ نظامًا مصرفيًا يوضّح نمط State، والوراثة، وإدارة المؤشرات الذكية. ستنشئ نظامًا يمكن أن تكون فيه الحسابات في حالات مختلفة (Active وFrozen وClosed)، ولكل حالة سلوكيات مميّزة لمعالجة المعاملات.
ستنظّم الشيفرة عبر ستة ملفات:
AccountState.h: عرّف البنية الأساسية لنمط State لحالات الحسابات.أنشئ فئة أساسية مجردة باسم
AccountStateمع أساليب افتراضية محضة:deposit(double amount): تُرجع true إذا كان الإيداع مسموحًا، وfalse بخلاف ذلكwithdraw(double amount): تُرجع true إذا كان السحب مسموحًا، وfalse بخلاف ذلكgetStateName(): تُرجع اسم الحالة كسلسلة نصية
نفّذ ثلاث حالات ملموسة:
ActiveState: Allows both deposits and withdrawals, returns"Active"FrozenState: Allows deposits but rejects withdrawals, returns"Frozen"ClosedState: Rejects both deposits and withdrawals, returns"Closed"
Account.h: أنشئ تسلسلًا هرميًا للحسابات مع إدارة الحالة.أنشئ فئة أساسية باسم
Accountتتضمن:- رقم الحساب (سلسلة نصية)، واسم المالك، والرصيد
- مؤشرًا من النوع
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: يتضمن متطلبًا للحد الأدنى من الرصيد (يُمرَّر إلى الباني). أعد تعريف withdraw للتحقق أيضًا مما إذا كان السحب سيؤدي إلى انخفاض الرصيد عن الحد الأدنى؛ وإذا حدث ذلك، فاطبع"Cannot go below minimum balance of [minimum]". ويُرجع"Savings"لنوع الحساب.CheckingAccount: يتضمن حدًا للسحب على المكشوف (يُمرَّر إلى الباني). يسمح بالسحب حتى (الرصيد + overdraftLimit). ويُرجع"Checking"لنوع الحساب.
Transaction.h: مثّل المعاملات في صورة كائنات.أنشئ فئة باسم
Transactionتسجّل:- نوع المعاملة (سلسلة نصية: "Deposit"، "Withdrawal"، "Transfer")
- المبلغ
- رقم الحساب المعني
- حالة النجاح (bool)
أضف أسلوبًا باسم
getDescription()يُرجع"[type]: $[amount] on [accountNumber] - [Success/Failed]"Customer.h: أنشئ عميلًا يمتلك عدة حسابات.يمتلك
Customerاسمًا ومعرّفًا ومتجهًا من النوع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يجمع هذا التحدي بين نمط State لإدارة سلوكيات الحسابات، والوراثة لأنواع الحسابات المختلفة، والمؤشرات الذكية لعلاقات الملكية، وتتبع المعاملات؛ وهي جميعًا مفاهيم أساسية أتقنتها طوال هذه الدورة.
جرّب بنفسك
#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: Print transaction count as "Transactions: [count]"
return 0;
}
جميع دروس البرمجة كائنية التوجه
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مراجعة - الحاويات العامةتدرّب بنفسك: مترجم C++ عبر الإنترنت