Friday, April 26, 2024 21:55

Cuprins >> Delegați, Expresii Lambda, Evenimente > Tiparul observatorului

Tiparul observatorului

Conform Microsoft, tiparul observatorului este un design comportamental care permite unui obiect să notifice alte obiecte despre modificări ale stării sale.

Multor programatori începători (și chiar și celor mai experimentați) le este greu să înțeleagă legătura dintre delegați și evenimente, iar fundația pe care este construită această legătură este reprezentată tocmai de tiparul observatorului. Pentru ca acest concept să fie ușor de înțeles, astfel încât să puteți învăța tranziția la evenimente mai ușor, să luăm un exemplu simplu. Să ne imaginăm că vrem să punem în aplicare un sistem care să alerteze mașinile atunci când vine un tren, astfel încât acestea să se oprească. Prima cărămidă a acestui sistem va fi reprezentat de o clasă numită SemnalTren:

Nu este nimic complicat în ceea ce privește clasa mea: am adăugat un Action, VinTrenuri, și amintiți-vă, un Action este doar un delegat care ia între 0 și 16 parametri și returnează void. Acesta va reprezenta semnalul meu de tren. În cele din urmă, am adăugat o metodă publică numită VineUnTren(), care va efectua toate acțiunile necesare la sosirea unui tren și de asemenea, va informa pe oricine este interesat în venirea trenului, invocând delegatul VinTrenuri.

Următorul pas este să declar obiectele care sunt interesate de venirea unui tren, așa că voi adăuga o clasă Masina:

În clasa mea Masina, am un constructor supraîncărcat care acceptă o instanță SemnalTren, iar în interiorul acestui constructor adaug o metodă numită OpresteMasina() la delegatul înlănțuit VinTrenuri. Acest lucru poate fi înțeles ca „Abonez metoda OpresteMasina() la delegatul VinTrenuri, astfel încât atunci când este invocat acest delegat, metoda mea va fi apelată și ea”, sau pur și simplu „hei, adăugă-mă la lista abonaților acestui delegat”.

Și tocmai acesta este modul .NET de a implementa tiparul observatorului: prin abonarea metodelor noastre la lanțul de metode al unui delegat, ori de câte ori va fi invocat acel delegat, toate metodele care s-au abonat vor fi apelate, astfel încât acestea vor „observa” că delegatul a fost invocat. În exemplul meu, toate instanțele Masina care se vor abona la delegatul VinTrenuri vor observa când acest delegat va fi invocat (când semnalul de tren va fi declanșat și toate metodele abonate vor fi notificate).

Acum, tot ce trebuie făcut este să punem efectiv întregul sistem în funcțiune:

Primul lucru de reținut este faptul că un delegat ține evidența nu doar a metodei pe care o va apela ulterior, ci și a obiectului de care acea metodă aparține. Am explicat în lecția despre delegați că aceștia au două proprietăți importante: Method și Target. Din acest motiv, nu trebuie să declar un nume pentru instanțele mele de tip Masina, le pot instanția anonim, folosind direct operatorul new. Întrucât toate se abonează la delegatul VinTrenuri în interiorul constructorului lor, delegatul își va aminti fiecare instanță care a subscris la el.

În continuare, observați că atunci când apelez metoda VineUnTren(), aceasta va invoca delegatul, ceea ce înseamnă că delegatul va apela orice metodă OpresteMasina() a oricărei instanțe Masina care s-a abonat la el, notificând efectiv fiecare abonat.

Aceasta este rezultatul care dovedește faptul că toate cele 5 instanțe Masina abonate s-au oprit atunci când a fost invocat delegatul semnal de tren:

Tiparul observatorului în C#

Tags: , , , , ,

Leave a Reply



Follow the white rabbit