![]() |
![]() |
![]() ![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 1 429 Pomógł: 195 Dołączył: 6.10.2008 Skąd: Kraków/Tomaszów Lubelski Ostrzeżenie: (0%) ![]() ![]() |
Witam, mamy taką często sytuację że w programie graficznym mamy coś takiego jak "Opcje", "Parametry" czy coś w tym stylu. Wpisujemy je np. w różnych inputach, textareach, radio buttonach a potem zapisujemy ustawienia. Dostęp do tych ustawień musi być z całego programu, z każdej klasy, która ich wymaga. Często jest tak że te klasy są gdzieś bardzo głęboko w hierarchii i nieodpowiednim jest pisanie czegoś takiego
Kod //taki glupi przyklad options = UI->getOptions(); UI->dom->parter->pokoj->krzeslo->setOptions(options) Wiem że takie rozw. jak powyżej jest nieeleganckie i łamie zasady programowania obiektowego. Drugim rozwiązaniem może być przechowywanie tych ustawień w klasie statycznej i prosty dostęp za pomocą Opcje::parametr1. Jednak to mimo że wygodne, ponoć też jest niepoprawne (zalatuje zmiennymi globalnymi rodem z C). Jaki jest wg Was najlepszy sposób na przechowywanie i przekazywanie tych danych? Lub ogólniej, jeżeli klasa "krzesło" (z powyższego przykładu) potrzebuje jakiejś danej z klasy "UI", to jak mu ją przekazać w najbardziej elegancki sposób? Pozdrawiam Ten post edytował MateuszS 22.11.2013, 19:27:45 |
|
|
![]() |
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 205 Pomógł: 43 Dołączył: 5.03.2012 Ostrzeżenie: (0%) ![]() ![]() |
Ale czemu klasy statycznej? Wystarczy że stworzysz jedną instancję normalnej klasy w przestrzeni globalnej programu i wtedy będziesz miał dostęp do niej z każdego miejsca.
Co do wężyków. Jeśli w Twoim przypadku jest "krzesło" z metodą "setOptions" to nie musisz robić takich węzyków, jeśli używasz metody "ciągnięcia" danych zamiast ich "pchania". Chodzi o to, że dane potrzebne krzesłu mógłbyś w momencie tworzenia tego krzesła pobierać właśnie z obiektu globalnego. Poza tym, takie węzyki trochę łamią zasadę enkapsulacji. Chodzi o to, że "włamujesz" się po krzesło przez dom->parter->pokoj. To może być przydatne czasami ale dobrze jest przemyśleć sobie czy takie rozwiązanie jest naprawdę bezpieczne. Dam może inny przyklad, trochę bardziej realny. Mam silnik 3d i występują tutaj obiekty przestrzenne (na przykład kula, stożek, sześcian itp). Każdy z nich ma swoją pozycję w przestrzeni. Powiedzmy, że jest to klasa 'Obiekt3d' , a z niej dziedziczą klasy "Kula", "Stożek" , "Sześcian". Natomiast każda z tych klas przetrzymuje referencję do obiektu klasy "Wektor3", która jest ową pozycją, składającej się z 3 pól "x" , "y" , "z" , które są zmiennymi "float". Najłatwiej byłoby zrobić "kształt->pozycja->x = float" żeby zmienić pozycję obiektu na osi x w przestrzeni 3d. Ale co jeśli ze zmianą pzycji musi się wiązać jakaś inna operacja? Na przykład chcemy żeby przy zmianie pozycji sprawdzone zostało czy ten obiekt nie koliduje z innym obiektem. Jeśli zmienimy jedynie wartość x wewnętrznej referencji do pozycji obiektu wtedy coś takiego się nie stanie. Rozwiązaniem jest wprowadzenie do klasy "Obiekt3d" nowej metody "ustawPozycje(Wektor3 pozycja)" i w niej można wykonywać wymagane operacje - zmienić pozycję używając zmiennej przekazanej do metody i skalkulować kolizje. " Mój sceptycyzm wynika z tego raczej że do takich ustawień można się dostać z każdego miejsca programu." No tak , można sie dostać ale co z tego? (IMG:style_emoticons/default/smile.gif) Tutaj trzeba rozgraniczyć pomiędzy modułami i przyjąć określoną strategię komunikacji między nimi. Czyli na przykład mając moduł UI i moduł Ustawienia z na przykład jakąś domyślną wielkością czcionki, którą można zmienić - komunikujemy tą zmianę modułowi Ustawienia z modułu UI. Trudno bowiem na przykład zmieniać domyślną wielkość czcionki z modułu Drukowanie. Generalnie tyle mogę powiedzieć z własnego doświadczenia.. mam jesszcze trochę innych, negatywnych takich jak programowanie oparte na zdarzeniach, ale nie polecam - 50% kodu to była obsługa zdarzeń, więc kod nic nie wnoszący do programu. Aha i apropos tego UI. Jest jeszcze jedno rozwiązanie, jesli na prawdę nie chcesz zmiennych globalnych lub po prostu chcesz mieć wiele instancji jednej klasy: poszukaj w internecie na temat wzorca projektowego "Composite". Chodzi o to, ze kazdy element UI przetrzymuje referencje do rodzica, czyli "krzesła zna pokój"" w ktorym się znajduje, "pokój" zna "dom" a "dom" zna "UI" do którego należy więc można w momence dodania obiektu do UI przechwycić to UI z poziomu obiektu dodawanego. Ja tego rozwiązana nie polecam. Jako, że używam raczej Javy - ciągle miałem problemy z pustymi wskaźnikami . Poza tym w rezultacie okazuje się się, że w danym momencie istnieje tylko jeden interfejs użytkownika. A żeby zmienić ten interfejs, wystarczy do zmienne globalnej, trzymającej ten interfejs (UI) przypisać po prostu inny... I nagle mamy zupełnie inne GUI - przydatne przy przechodzeniu pomiędzy ekranami. No i w rezultacie nie wiem czy wszystkie przypadki nie redukują się do pojedynczej instancji. Generalnie kompozycja to trudny temat. Ja radzę nie "włamywać" się w obiekty złożone, co bardziej przypomina trochę "włażenie pod skórę" - hackowanie. Najważniejsza jest jednak kontrola nad tym. W wielu przypadkach obiekty można uznać bardziej za struktury danych. W C++ jest do tego "struct" . Takie Ustawienia w wielu przypadkach mogłyby być po prostu właśnie zwykłą strukturą danych, co odpowiada klasie z upublicznionymi polami. Jednak rzadko z czymś takim mam do czynienia. Warto sobie to przemyśleć zanim napisze się linijkę kodu (IMG:style_emoticons/default/smile.gif) |
|
|
![]() ![]() |
![]() |
Aktualny czas: 17.10.2025 - 06:49 |