I na ovom sajtu:
http://www.akadia.com/services/dotnet_delegates_and_events.html, mozes procitati o delegatima.
U tekstu mozes pronaci sledecu recenicu: 'A delegate will allow us to specify
what the function we'll be calling looks like without having to specify which function to call'.
Znaci, delegat 'pomaze' kada NIJE potrebno
EKSPLICITNO pozvati funkciju, nego nam je vazno da znamo, kako pise u ovoj recenici: 'what the function we'll be calling looks like', ili da
to prevedemo na OO jezik: potrebno je navesti
POTPIS pozvane funkcije.
Evo i jednog primjera: imao sam korisnicki zahtjev da se sa istog UI-a (user interface), radi sa razlicitim, da tako kazem, entitetima (recimo, kompanije i kontakti). Dakle, na istom UI-ju,
trebalo je odraditi funkcionalnosti tipa: Edit, Save, Delete, Print ... Znaci, ako dodajem novu kompaniju, klik na dugme 'Save', poziva metod za upis nove kompanije u bazu - isto i ako dodajem novi
kontakt za neku kompaniju. Ako sam editovao (bilo kompaniju, bilo kontakt), klik na 'Save' treba da pozove metod za 'Update' odgovarajucih podataka u bazi.
Znaci, mi ne znamo,
unaprijed, koji ce metod biti pozvan klikom na dugme 'Save'. U eventhandler-u za dogadjaj Click, dugmeta 'Save', cemo upisati da se poziva metod odgovarajuceg potpisa (delegate).
Na drugom mjestu u programu cemo 'podmetnuti' zeljeni metod istog
POTPISA kao i metoda, koji se ocekuje u eventhandler-u Click dogadjaja.
Evo i koda.
Kreiracemo klasu u kojoj cemo definisati delegat:
Code:
public class MediatorCompany_Person
{
public delegate void InsertObject(); //ovo je definicija delegata: to je metod bez parametara i bez povratne vrijednosti
public InsertObject currentInsert; // referenca na metod, koji se poziva iz buttonSave.Click
}
MediatorCompany_Person medComPer = new MediatorCompanyPerson();
Sam eventhandler, za dogadjaj Click, od dugmeta 'Save', izgleda ovako:
Code:
// eventhandler za dugme save ...
private void buttonSave_Click(object sender, EventArgs e)
{
// pozovi odgovarajucu funkciju iz medijatora
if (medComPer.currentInsert != null)
medComPer.currentInsert();
}
Kao sto vidis, nije eksplicitno pozvan metod za: 'dodavanjeNoveKompanije', 'dodavanjeNovogKontakta', 'UpdatePostojeceKompanije' itd -> eksplicitno je pozvan metod, koji se u datom trenutku, zavisno
od logike programa, nalazi u 'currentInsert'.
Negdje u programu, zavisno od logike (konteksta) stoji, recimo da je:
Code:
medComPer.currentInsert = metodNovaKompanija;
ili:
Code:
medComPer.currentInsert = metodNoviKontakt;
Vazno je da metodNovaKompanija ima isti potpis kao i 'InsertObject' delegat iz definicije medijator klase, to jest da je bez parametara i da nema povratnu vrijednost:
Code:
void metodNovaKompanija()
{
// kod za 'insert' u bazu ...
}
Na taj nacin, logika programa obezbjedjuje da se u eventhandler-u UVIJEK poziva odgovarajuci metod, bez znanja koji je metod, zaista, EKSPLICITNO, pozvan.
Ovo moze da se uradi i bez delegata:
Code:
// eventhandler za dugme save ...
private void buttonSave_Click(object sender, EventArgs e)
{
if (trebaUbacitiNovuKompaniju)
metodNovaKompanija();
else
if (trebaUbacitiNoviKontakt)
metodaNoviKontakt();
else
if (trebaUpdateKompanija)
metodUpdateKompanija();
else (...)
...
}
Ako se, primjera radi, budu dodavale neke nove funkcionalnosti, moraces da dodajes novi if/else uslov u gore navedenom, visestrukom, 'if-else'-u, moraces da vodis racuna o set/reset bool promenljivih tipa
'terbaToiTo...', itd.
Primjenom delegata, u gornjem primjeru, kod za eventhandler se nikada nece mijenjati - u logici programa ces dodavati metode za nove funkcionalnosti i 'podmetati' ih u 'medComPer.currentInsert',
kao sto je navedeno u primjeru.
Programming is fun, but writing good software is hard ...