Architecture Net

Полный пример


Программа DelegateAccount иллюстрирует использование делегатов на примере банковского счета. В файле DelegateAccount. cpp объявляется делегат NotifyCallback. Методы, соответствующие по сигнатурам методам, описанным в объявлении делегата, реализованы в классе DelegateAccount. Метод Мат (Главный) создает экземпляры делегатов и объединяет их различными способами. Указатель на экземпляр делегата передается экземпляру класса Account (Счет), который использует инкапсулированные делегатом методы для выдачи соответствующего ситуации сообщения об овецдрафте.

Обратим внимание на динамичную и гибкую связь между этими объектами. Класс Account (Счет) не знает, какой из методов будет использоваться для выдачи сообщения в случае овердрафта. Он просто вызывает делегат, который по очереди вызывает все методы из списка, причем адаптацию списка можно производить и в процессе выполнения программы.


Приведем исходный код класса Account (Счет):

//Account.h
_delegate void NotifyCallback(Decimal balance); // делегировать NotifyCallback (Десятичный баланс);
_gc class Account
// класс сборщика мусора Счет
{
private: // частный
Decimal balance; // Десятичный баланс
NotifyCallback *pNotifyDlg; public:
Account(Decimal bal, NotifyCallback *pDlg) // Счет
{
balance = bal; // баланс
pNotifyDlg = pDlg;
}
void SetDelegate(NotifyCallback *pDlg)
{
pNotifyDlg = pDlg;
}
void Deposit(Decimal amount) // Депозит (Десятичное количество)
{
balance = balance + amount;
// баланс = баланс + количество;
}
void Withdraw(Decimal amount) // Десятичное количество
{
balance = balance - amount;
// баланс = баланс - количество;
if (balance < 0) // если (баланс <0) ситуация кредита
//по текущему счету
pNotifyDlg(balance); // баланс - обратный вызов
}
_property Decimal get_Balance() // Десятичное число
}
return balance; // баланс
}
_property void set_Balance(Decimal balance) // Десятичный
// баланс
{
this->balance = balance; // баланс
}
};

Приведем исходный код объявления и тестирования делегата:

//DelegateAccount.h
_gc class DelegateAccount
// класс сборщика мусора DelegateAccount
{
public:
static void Main() // Главный
{
// создать делегат для статического метода NotifyCustomer
NotifyCallback *pCustDlg = new NotifyCallback(
О, // ноль для статического метода NotifyCustomer
NotifyCustomer);
// создать делегат для статического метода NotifyBank
NotifyCallback *pBankDlg = new NotifyCallback(
О, // ноль для статического метода NotifyBank
NotifyBank);
// объявить, что делегат-объект используется // объектом Account NotifyCallback *pCurrDlg;
// псевдокод: pCurrDlg = pCustDlg + pBankDlg pCurrDlg = static_cast<NotifyCallback *>(
Delegate::Combine(pCustDlg, pBankDlg)); // Делегат:
// Объединение
// создать объект Account и установить
// делегат для использования
Account *рАсс = new Account(100, pCurrDlg); // новый Счет
Console::WriteLine(
"balance = {0}", _box(pAcc->get_Balance())); // баланс
// вызвать делегат два раза
pAcc->Withdraw(125); // обратный вызов через делегат!
Console::WriteLine(
"balance = {0}", _box(pAcc->get_Balance())); // баланс
pAcc->Deposit(200);// Депозит pAcc->Withdraw(125);
// кредит по текущему счету не нужен, // так что не вызывать обратно
Console::WriteLine(
"balance = {0}", _box(pAcc->get_Balance())); // баланс
// альтернатива: pCurrDlg - = pBankDlg
pCurrDlg = static_cast<NotifyCallback *>(
Delegate::Remove(pCurrDlg, pBankDlg)); // Делегат::
// Удалить
// установить новый делегат, который используется
// объектом Account
pAcc->SetDelegate(pCurrDlg);
// вызвать делегат
pAcc->Withdraw(125); // обратный вызов через делегат!
// создать экземпляр, требуемый для экземпляра делегата DelegateAccount *pda = new DelegateAccount();
// создать делегат для экземпляра метода Notifylnstance NotifyCallback *p!nstDlg = new NotifyCallback(
pda, // отличный от нуля для метода Notifylnstance
Notifylnstance);
// дополнительный код: pCurrDlg + = plnstDlg
pCurrDlg = static_cast<NotifyCallback *>(
Delegate::Combine(pCurrDlg, plnstDlg)); // Делегат:
// Объединение
// установить новый делегат, который используется
// объектом Account pAcc->SetDelegate(pCurrDlg);
pAcc->Withdraw(125); // обратный вызов через делегат!
}
private: // частный
static void NotifyCustomer(Decimal balance) // Десятичный
// баланс
{
Console::WriteLine("Dear customer,"); // Дорогой клиент,



Console::WriteLine(
" Account overdrawn, balance = {0}", // Счет превышен,
// баланс
_box(balance)); // баланс
}
static void NotifyBank(Decimal balance) // Десятичный баланс

{
Console::WriteLine("Dear bank,"); // Дорогой банк,

Console::WriteLine(
" Account overdrawn, balance = {0}", // Счет превышен,
// баланс
_box(balance)); // баланс
}
void Notifylnstance(Decimal balance) // Десятичный баланс
{
Console::WriteLine("Dear instance,"); // Дорогой
// представитель
Console::WriteLine(
" Account overdrawn, balance = {0}", // Счет превышен,
// баланс
_box(balance)); // баланс
}
};

Ниже приведен результат работы программы. Обратите внимание на то, какие методы вызываются в зависимости от операций, выполняемых делегатом на каждом этапе.

balance = 100
Dear customer,
Account overdrawn, balance = -25
Dear bank,
Account overdrawn, balance = -25
balance = -25
balance = 50
Dear customer,
Account overdrawn, balance = -75
Dear customer,
Account overdrawn, balance = -200
Dear instance,
Account overdrawn, balance = -200

А вот и перевод выдачи:

баланс = 100 Дорогой клиент,
Овердрафт по счету, баланс =-25
Дорогой банк,
Овердрафт по счету, баланс =-25
баланс =-25
баланс = 50
Дорогой клиент,
Овердрафт по счету, баланс =-75
Дорогой клиент,
Овердрафт по счету, баланс =-200
Дорогой представитель,
Овердрафт по счету, баланс =-200

CompEbook.ru Железо, дизайн, обучение и другие


Содержание раздела