Dekompozycja systemu, jak uniknąć Singletona

0

Mam problem z zaprojektowaniem pewnego systemu. I na tym etapie przychodzi mi do głowy tylko Sigleton, a wiem, że nie jest to zbyt dobre rozwiązanie i można to nazwać antywzorcem.

Potrzebuję klasę, która będzie, że tak powiem nadzorcą w całym systemie, będzie przechowywała stany udostępniane dla wszystkich innych obiektów, a jednocześnie będzie wykonywała operacje na danych otrzymywanych z innych podsystemów. Np. otrzymam z zewnętrznego systemu polecenie zmiany trybu pracy jakiegoś urządzania, albo zechcę je włączyć/wyłączyć. Odbiorę te dane w klasie odbierającej (wywołam jakąś metodę z klasy głównej Supervisor, np. sprawdzenie poprawności danych, czy się mieszczą
w odpowiednich zakresach, zmiane stanu w zależności od tego co przyjdzie.
Zakładam, że podsystemów będzie kilka. System sterujący temperaturą, system sterujący oświetleniem, system do sterowania jeszcze tam czegoś.
Komunikacja z systemem sterującym temperaturą będzie wyglądała w sposób nastepujący (dla innych analogicznie).
Przychodzi polecenie z systemu zewnętrznego po sieci aby ustawić temperaturę na 50 stopni. Mam klasę Supervisor jako tą główną (może istnieć tylko jedna jej instancja (no właśnie?) bo dane, które się w niej znajdują i metody które udostępnia muszą być wspólne i aktualne dla wszystkich innych podsystemów.
Mam Supervisor_Receiver, która odbiera mi dane z zewnątrz, jest takim łącznikiem z podsystemem, który może całością sterować.) Odbieram dane, (przekazuję je do Supervisor np. w celu sprawdzenia, jak temperatura będzie np. powyżej 45 stopni o ignoruję wiadomość całkowicie), jak mieści się w zakresie to wysyłam odpowiednie polecenie z wartością na jaki ma być ustawiona. Jak temperatura się zmieni to podsystem mi wysyła jakieś potwierdzenie OK czy coś, że wszystko gra.
No i jak to teraz przełożyć na kod?
Tworzę klasę Supervisor, czy ona powinna być statyczna?
Na samym początku klasa główna powinna zainicjować komunikację z innymi podsystemami. Zastanawiam się jak to rozwiązać. Czy utworzyć osobną klasę np. Connections zainicjować tam wszystkie połączenia, a następnie przekazać do klasy głównej referencję?

3

Dlaczego chcesz mieć jakiś god object robiący wszystko i będący centralnym punktem aplikacji, a nie chcesz, aby podsystemy wymieniały konkretne informacje między sobą?

0

Możesz użyć dependency injection i jakiś kontener IoC żeby komponenty mogły się ze sobą porozumiewać bez twardych powiązań

0

Chciałbym to jak najbardziej zdekomponować i rozdzielić, tylko nie do końca wiem jak. Istnieją pewne zależności które muszą być spełnione.
W systemie istnieje/musi istnieć właśnie taki Supervisor, który wszystkim zarządza i przez którego wszystko przepływa (tego zmienić nie mogę), czy da się to zrobić inaczej niż za pomocą "Super Obiektu"? Urządzenia mogą się komunikować tylko przez niego. Jestem jak najbardziej za tym by do tego "Główngo obiektu" trafiały tylko te już konieczne informacje, bez potrzeby rzucania mu wszystkiego, natomiast ośrodkiem decyzyjnym jest ten centralny podsystem. Napisałem sobie Observera, który odbiera mi konkretne wiadomości, i samo otrzymywanie wiadomości do przetworzenia chcę wywalić do osobnej klasy. Natomiast po tym jak je otrzymam i sprawdzę, muszę je przetworzyć właśnie w tym centalnym ośrodku.

0

Wydaje mi się, że wychodzisz od implementacji systemu, a nie od jego koncepcji, stąd narastające wątpliwości.

Ja bym wyszedł od czegoś prostszego, tj. od konceptów:

Urządzenie -- abstrakcja urządzenia, reaguje na komendy, umożliwia odczyt parametrów
NadzorcaUrządzenia -- odczytuje parametry nadzorowanego urządzenia, wysyła komendy do urządzenia
CentralaSterująca -- aktywuje nadzorców urządzenia, odczytuje dane od nadzorców, wysyła komendy do nadzorców, korzysta z planera do określenia kolejnych akcji
PlanerAkcji -- na podstawie parametrów z centrali sterującej generuje komendy do wykonania.

Zauważ, że nie ma tu mowy o klasach GOD, implementacji, dzieleniu stanu, singletonach etc.

Jest za to punkt wyjścia do dopracowania w koncepcji, np. jak zbierać parametry urządzeń, tj. tryb pull (odpytywanie nadzorców o parametry), tryb push (nadzorcy powiadamiają centralę), czy tryb mieszany (np. push w przypadku podniesienia alarmu, np. temperatura > xyz, tu doszłyby koncepty Alarm, Czujnik etc. i rozszerzyłby się zakres odpowiedzialności NadzorcyUrzadzenia).

Co do Planera, to nie znam specyfiki problemu, żeby wiedzieć czy PlanerAkcji potrzebuje wiedzy o topologii urządzeń (jak są ze sobą powiązane), jakichś innych reguł. W każdym razie na podstawie wyjścia z PlaneraAkcji, CentralaStreujaca wysyłałaby komendy do Nadzorców, a te z kolei do Urządzeń.

Mając "model biznesowy", możesz myśleć o tym jak dorzucić "klasy techniczne", tj. fabryki / repozytoria / etc.

Powodzenia :)

pozdr,

0

Prawdopodobnie twój supervisor powinien być wzorcem mediatora, oto definicja z wiki:

Wzorzec mediatora umożliwia zmniejszenie liczby powiązań między różnymi klasami, poprzez utworzenie mediatora będącego jedyną klasą, która dokładnie zna metody wszystkich innych klas, którymi zarządza. Nie muszą one nic o sobie wiedzieć, jedynie przekazują polecenia mediatorowi, a ten rozsyła je do odpowiednich obiektów.

Trzeba tylko uważać na to o czym pisze @somekind, mediator łatwo może zostać takim god object,

1 użytkowników online, w tym zalogowanych: 0, gości: 1