Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> Gdzie deklarować obserwatorów klasy centralnej?
q3trm
post 30.06.2013, 13:29:34
Post #1





Grupa: Zarejestrowani
Postów: 83
Pomógł: 1
Dołączył: 26.02.2013

Ostrzeżenie: (0%)
-----


Witam.

Mam taki dylemat z zadeklarowaniem obserwatorów klasy RegistrationUserModel

  1.  
  2. class RegistrationUserModel implements Observable {
  3.  
  4. private $observers = array();
  5. private $status = array();
  6.  
  7.  
  8. public function attach(Observer $observer) {
  9.  
  10. $this->observers[ ] = $observer;
  11.  
  12. }
  13.  
  14. public function detach(Observer $observer) {
  15.  
  16. $newobservers = array();
  17.  
  18. foreach ($this->observers as $obs) {
  19. if (($obs !== $observer)) :
  20.  
  21. $newobservers[ ] = $obs;
  22. endif;
  23.  
  24. $this->observers = $newobservers;
  25. }
  26. }
  27.  
  28. public function notify() {
  29.  
  30. foreach ($this->observers as $obs) :
  31. $obs->update($this);
  32. endforeach;
  33. }
  34.  
  35. private function setStatus($name, $status) {
  36.  
  37. $this->status[$name][ ] = $status;
  38. }
  39.  
  40. public function getStatus($name) {
  41.  
  42. if (isset($this->status[$name])) :
  43.  
  44. return $this->status[$name];
  45.  
  46. endif;
  47. }
  48.  
  49. /////////////////////////// jakaś logika klasy //////////////////////////////////////
  50. /////////////


  1. class RegistrationObserver implements Observer {
  2.  
  3. public function update(Observable $observable) {
  4.  
  5. $warningMessage = $observable->getStatus('Warning'); // pobiera tablice z zdarzeniem
  6.  
  7. Registry::register('Warning')->setWarning($warningMessage); //przekazuje klasie Warning zdarzenie
  8.  
  9. }
  10.  
  11. }


Wywołanie metody attach() w konstruktorze klasy centralnej(podmiotu obserwacji) - jest dobrą praktyką?. Czy może lepiej zadeklarować obserwatorów w kontrolerze aplikacji?



Go to the top of the page
+Quote Post
Dejmien_85
post 30.06.2013, 16:02:50
Post #2





Grupa: Zarejestrowani
Postów: 251
Pomógł: 23
Dołączył: 23.04.2013

Ostrzeżenie: (0%)
-----


Cytat(q3trm @ 30.06.2013, 14:29:34 ) *
Wywołanie metody attach() w konstruktorze klasy centralnej(podmiotu obserwacji) - jest dobrą praktyką?


Uważam, że taka praktyka jest... niecodzienna. ; )

Metoda attach() powinno być "zwykłą" metodą klasy podmiotu wywoływaną tylko wtedy, gdy nowy obserwator chce się zarejestrować na listę "paCZających" - i ta metoda powinna go zarejestrować.

Szkoda, że nie napisałeś czegoś więcej o swoim projekcie, bo ciężko cokolwiek więcej powiedzieć - no, mogę dodać, że RegistrationObserver wygląda intrygująco [wygląda mi to na high coupling - skąd obserwator pobiera dane? I czy posiada jakieś dane o sobie? Obserwator powinien być całkowicie niezależnym obiektem, który aktualizuje dane (od podmiotu) na których mu zależy]. Ciekawi mnie to, jak rozumiesz wzorzec obserwatora i jak chcesz go zaimplementować do swojej aplikacji.

Gdybyś napisał kilka słów o obserwatorach, wtedy łatwiej byłoby ten temat dalej pociągnąć. Napisz może jakich obserwatorów chciałbyś stworzyć i jak ogólnie widzisz działanie swojej aplikacji ze wzorcem obserwatora.
Go to the top of the page
+Quote Post
q3trm
post 30.06.2013, 18:06:49
Post #3





Grupa: Zarejestrowani
Postów: 83
Pomógł: 1
Dołączył: 26.02.2013

Ostrzeżenie: (0%)
-----


Mój projekt to prosta niekomercyjna strona firmowa z możliwością rejestracji rolleyes.gif na własnym MVC.

Tak sobie wymyśliłem, że warto, by było odprężyć model zajmującą się rejestracją nowych użytkowników. RegistrationUserModel to typowy model, "sprawdź, czy istnieje użytkownik w bazie jak nie, to użyj zarejestrowanego obserwatora ->attach()". W wymienionym przykładzie tą operacją jest przesłanie message do użytkownika o zaistniałym "faux pas".

Mój obserwator jest uzależniony od klasy Warning( Registry::register('Warning') - singleton), która zajmuję się przesyłaniem ostrzeżeń klientom, od klas aplikacji. Wiem, że klasa(Warning) mogła, by działać bezpośrednio w klasie RegistrationUserModel, ale chcę poeksperymentować snitch.gif .

W przyszłości zamierzam dodać kilka innych obserwatorów np: statystyki,logi itp.

Załóżmy, że obserwator w moim przykładzie ma własną logikę i jest niezależnym komponentem systemu, gdzie w takim razie powinna odbywać się rejestracja obserwatorów klasy RegistrationUserModel - jak pisałem wyżyj jest to aplikacja oparta na wzorcu MVC.
Go to the top of the page
+Quote Post
Dejmien_85
post 30.06.2013, 19:10:11
Post #4





Grupa: Zarejestrowani
Postów: 251
Pomógł: 23
Dołączył: 23.04.2013

Ostrzeżenie: (0%)
-----


Hmm, wydaje mnie się, przyjacielu, że chyba sobie troszkę eksperymentujesz z wzorcami. ; )

Wydaje mnie się także, że spoglądasz na wzorzec obserwatora przez pryzmat wzorca MVC. Jeśli chodzi o wzorzec obserwatora, to:

1. W podmiocie powinny znaleźć się:
- metody rejestracji oraz usuwania obserwatorów,
- metody odpowiedzialne za informowanie obserwatorów o tym, że coś się zmieniło (to na czym zależy obserwatorom, to co obserwują).
2. W podmiocie powinny znaleźć się cenne informacje (np. public variables, które są aktualizowane w jakiś sposócool.gif dla obserwatorów - w końcu to nimi są zainteresowani.
3. Podmiot obserwacji oraz obserwatorzy powinni być całkowicie niezależni od siebie, tj. podmiot posiada cenne info dla obserwatorów i informuje ich o tym, ze je ma i że następuje jakiś update danych itp, a obserwatorzy po otrzymaniu "cynku" robią aktualizację danych (np. zastępują swoje wartości wartościami podmiotu) i to za pomocą swoich metod.

Musisz się zastanowić, czy w ogóle będzie Ci tutaj potrzebny wzorzec obserwatora. W tym wzorcu obserwatorzy są tak naprawdę oddzielnymi bytami, które są zainteresowane informacjami od podmiotu. Obserwator to obiekt, który podchodzi do podmiotu i mówi mu: "Ej, Zią, słuchaj, jak będziesz wiedział coś o XYZ, to daj mi znać.". Podmiot mówi: "Okay."

Powiedzmy, że Podmiot ma jakąś informację, niech to będzie informacja na temat liczby zarejestrowanych użytkowników. Obserwatorzy są tym zainteresowani i czekają na "cynk". Gdy pojawia się nowy obserwator, wtedy wysyła info do Podmiotu o tym, że jest zainteresowany jego informacjami i żeby Podmiot wpisał go na listę, czyli Podmiot wywołuje metodę rejestracji i zapisuje Obserwatora na swoją listę. Załóżmy, że nagle zarejestruje się nowy użytkownik, wtedy skrypt automatycznie zmienia dane Podmiotu o rejestracji, dodaje +1 do infa o zarejestrowanych użytkownikach, a gdy zmienia się wartość, wtedy Podmiot automatycznie wysyła obserwatorom "cynk" o tym, że liczba się zmieniła - podmiot NIE mówi nawet o tym, o ile się zmieniła ta liczba, tylko po prostu daje cynk: "Ej, coś się zmieniło, zajrzyj do mnie". Wtedy Obserwatorzy zaczynają działać ze swoją logiką. Sami za pomocą swoich metod sprawdzają info o zarejestrowanych użytkownikach i aktualizują te dane.

Tylko pamiętaj, że podmiot ma różne dane, a każdy obserwator może być zainteresowany czymś innym, także warto jest informować o zmianach danych tylko tych obserwatorów, którzy są zainteresowani takimi danymi.

Co do implementacji tego wzorca w Twojej aplikacji - nie znam szczegółów Twojego systemu (logiki działania), także ciężko mi cokolwiek powiedzieć. Głupi nie jesteś, także jak troszkę pogłówkujesz, to z pewnością coś wymyślisz. ; )

Ewentualnie jakbyś chciał powiedzieć coś więcej na temat logiki swojej apki, wtedy moglibyśmy pomyśleć co można tutaj zrobić.

Napisz mi o co chodzi z tą rejestracją? Jakimi informacjami o rejestracji są zainteresowani obserwatorzy? Jakie informacje przekazuje im Podmiot? Najlepiej byłoby, gdybyś napisał jak chciałeś zaimplementować ten wzorzec - chodzi oczywiście o komunikację pomiędzy podmiotem i obserwatorami. Jak to widziałeś?

Ten post edytował Dejmien_85 30.06.2013, 19:14:16
Go to the top of the page
+Quote Post
q3trm
post 30.06.2013, 22:20:58
Post #5





Grupa: Zarejestrowani
Postów: 83
Pomógł: 1
Dołączył: 26.02.2013

Ostrzeżenie: (0%)
-----


Nie zawsze interpretacja własnych myśli jest zrozumiała, a więc kod z systemu wzięty.

  1. interface Observable {
  2.  
  3. function attach(Observer $observer);
  4. function detach(Observer $observer);
  5. function notify();
  6. }



  1.  
  2. class RegistrationUserModel implements Observable {
  3.  
  4. private $observers = array(); // tablica z aktywnymi obserwatorami klasy.
  5. private $status = array(); // rejestr zachodzących wydarzeń w klasie - na podstawie tej zmiennej obserwatorzy pobierają informacje na temat zdarzenia.
  6. private $POST;
  7. private $db;
  8.  
  9. public function __construct() {
  10.  
  11. $this->POST = Registry::register('Router')->getParams();
  12. $this->db = Registry::register('db');
  13. }
  14.  
  15. public function attach(Observer $observer) { // w kontrolerze została zadeklarowany obserwator RegistrationUserModel-> attach(new WarningObserver)
  16.  
  17. $this->observers[] = $observer;
  18. }
  19.  
  20. public function detach(Observer $observer) { // nie wiem gdzie to wywoływać
  21.  
  22. $newobservers = array();
  23.  
  24. foreach ($this->observers as $obs) {
  25.  
  26. if (($obs !== $observer)) :
  27.  
  28. $newobservers[] = $obs;
  29. endif;
  30.  
  31. $this->observers = $newobservers;
  32. }
  33. }
  34.  
  35. public function notify() { // informator obserwatorów o zajściu
  36.  
  37. foreach ($this->observers as $obs) :
  38. $obs->update($this);
  39. endforeach;
  40. }
  41.  
  42. private function setStatus($nameObserver, $nameStatus, $status) { //rejestruje zdarzenia zachodząca w klasie.
  43.  
  44. $this->status[$nameObserver][$nameStatus] = $status;
  45. }
  46.  
  47. public function getStatus($nameObserver) {
  48.  
  49. if (isset($this->status[$nameObserver])) :
  50.  
  51. return $this->status[$nameObserver];
  52.  
  53. endif;
  54. }
  55.  
  56. private function PasswordRepeatedCorrect($password,$password2) {
  57.  
  58. if ($password === $password2) {
  59. }
  60. else {
  61. $this->setStatus('WarningObserver', __FUNCTION__, 'Hasło nie zgadza się z powtórzonym.');
  62. return false;
  63. }
  64.  
  65. return true;
  66. }
  67.  
  68. ////////////////////// reszta metod ////////////////////////
  69.  
  70. public function saveNewUser() {
  71.  
  72. if (isset($this->POST['POST']) && $this->isNotEmpty($this->POST['POST']) && (count($this->POST['POST'])) == 12) {
  73.  
  74. if ($this->isExistsUser($this->POST['POST']['email'], $this->POST['POST']['nick']) && $this->PasswordRepeatedCorrect($this->POST['POST']['password'],$this->POST['POST']['password2'])) {
  75. ///// w przypadku zwrócenia false przez metode - jest rejestrowane zdarzenie w tablicy $status.
  76.  
  77.  
  78. ///////////////////////////////// zapis do bazy ////////////////////////////////////////
  79. } else {
  80.  
  81. $this->notify();
  82. // powiadomienie aktywnie zadeklarowanych obserwatorów o zajściu i wykonaniu przez nie metody update()
  83.  
  84. $this->redirection();
  85. }
  86. } else {
  87.  
  88. $this->setStatus('WarningObserver', __FUNCTION__, 'Proszę wypełnić wszystkie pola formularza.');
  89. $this->notify();
  90.  
  91. $this->redirection();
  92. }
  93. }
  94.  


  1. interface Observer {
  2.  
  3. function update(Observable $observable);
  4. }


  1. class WarningObserver implements Observer {
  2.  
  3. public function update(Observable $observable) {
  4.  
  5. $warningMessage = $observable->getStatus('WarningObserver'');
  6. // pobiera status wydarzeń(tablica z ostrzeżeniami) z podmiotu obserwacji
  7.  
  8. Registry::register('Warning')->setWarning($warningMessage);
  9. // konkretyzacja obiektu Warning i zapis tablicy z ostrzeżeniami.
  10. }
  11.  
  12. }


Ten post edytował q3trm 30.06.2013, 22:27:39
Go to the top of the page
+Quote Post
Dejmien_85
post 1.07.2013, 07:28:26
Post #6





Grupa: Zarejestrowani
Postów: 251
Pomógł: 23
Dołączył: 23.04.2013

Ostrzeżenie: (0%)
-----


Powinieneś dopieścić obserwatora - on powinien być niezależny, tj. powinien posiadać dane o swoim stanie (podczas tworzenia obiektu obserwatora Podmiot powinien automatycznie nadać jakiś stan obserwatorowi) i aktualizować je od Podmiotu. Oprócz interfejsu Observer powinieneś także stworzyć interfejs szczególny dla danego obserwatora - obserwator powinien tak naprawdę implementować co najmniej dwa interfejsy, tj.

- Interfejs Observer ma zajmować się aktualizacją danych i niczym więcej.
- Dodatkowy interfejs lub interfejsy powinny wykonywać wszelkie wymagane dodatkowe akcje (np. wyświetlać dane, przetwarzać je, czy przekazywać gdzieś dalej).
Adnotacja: Jeśli obserwator nie ma żadnych dodatkowych funkcji, wtedy oczywiście można pominąć dodatkowe interfejsy - jednak jaki jest wtedy sens bytu takiego obserwatora? Obserwator powinien coś zwracać. ; )

Zapoznaj się dobrze z wzorcem obserwatora i zastanów się dwa razy, czy aby na pewno to jest to, czego potrzebujesz w swojej aplikacji. *wink*

Ten post edytował Dejmien_85 1.07.2013, 07:42:35
Go to the top of the page
+Quote Post
q3trm
post 1.07.2013, 09:41:49
Post #7





Grupa: Zarejestrowani
Postów: 83
Pomógł: 1
Dołączył: 26.02.2013

Ostrzeżenie: (0%)
-----


Cytat(Dejmien_85 @ 1.07.2013, 08:28:26 ) *
Powinieneś dopieścić obserwatora - on powinien być niezależny, tj. powinien posiadać dane o swoim stanie (podczas tworzenia obiektu obserwatora Podmiot powinien automatycznie nadać jakiś stan obserwatorowi) i aktualizować je od Podmiotu. Oprócz interfejsu Observer powinieneś także stworzyć interfejs szczególny dla danego obserwatora - obserwator powinien tak naprawdę implementować co najmniej dwa interfejsy, tj.

- Interfejs Observer ma zajmować się aktualizacją danych i niczym więcej.
- Dodatkowy interfejs lub interfejsy powinny wykonywać wszelkie wymagane dodatkowe akcje (np. wyświetlać dane, przetwarzać je, czy przekazywać gdzieś dalej).
Adnotacja: Jeśli obserwator nie ma żadnych dodatkowych funkcji, wtedy oczywiście można pominąć dodatkowe interfejsy - jednak jaki jest wtedy sens bytu takiego obserwatora? Obserwator powinien coś zwracać. ; )

Zapoznaj się dobrze z wzorcem obserwatora i zastanów się dwa razy, czy aby na pewno to jest to, czego potrzebujesz w swojej aplikacji. *wink*


Wiadome, że w moim przykładzie observer jest bezsensu, ale dobrze jest czasami zrobić coś w kierunku edukacyjnym rolleyes.gif .

Jeszcze znalazłem lepszy sposób rejestracji obserwatorów w klasie podmiotu obserwacji.

  1.  
  2. abstract class RegistrationObserver implements Observer {
  3.  
  4. private $registration;
  5.  
  6. public function __construct(RegistrationUserModel $registration) {
  7.  
  8. $this ->registration = $registration;
  9. $registration -> attach($this);
  10. // Tu zachodzi rejestracja observatora w klasie RegistrationUserModel
  11.  
  12. }
  13. abstract public function update (RegistrationUserModel $registration);
  14. }
  15.  
  16. class SecurityMonitor extends RegistrationObserver
  17. class Statistic extends RegistrationObserver
  18. class Logs extends RegistrationObserver
  19.  
  20. new SecurityMonitor ($registration);
  21. new Statistic ($registration);
  22. new Logs ($registration);
  23.  


Powyższy przykład wydaje mi się bardziej przejrzystszy.

Zawsze można iść na łatwiznę i użyć biblioteki SPL snitch.gif
Go to the top of the page
+Quote Post
nospor
post 1.07.2013, 09:49:21
Post #8





Grupa: Moderatorzy
Postów: 36 442
Pomógł: 6290
Dołączył: 27.12.2004




Ja obiekty obserwatorów tworze dopiero wtedy gdy potrzeba, czyli np. gdy pojawi sie obiekt obserwowany i rzuca konkretnym eventem.
http://nospor.pl/wzorzec-obserwator.html


--------------------

"Myśl, myśl, myśl..." - Kubuś Puchatek || "Manual, manual, manual..." - Kubuś Programista
"Szukaj, szukaj, szukaj..." - Kubuś Odkrywca || "Debuguj, debuguj, debuguj..." - Kubuś Developer

Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 18.04.2024 - 07:34