Ustawienia interfejsu w metodzie statycznej

0

Witam mam program z wieloma kontrolkami, przyciskami itp ktore zmieniaja jakies wartosci zmiennych i musze miec dostep do nich z kazdego miejsca programu. Lepiej w klasie z GUI zrobic pola statyczne dla tych zmiennych czy moze stworzyc calkiem nowa klase Parametry?

2

Singleton - Parametry.

2

Dużo sensowniej mieć obiekt przechowujący te parametry. Ale ja bym sie zastanowił czy czasem nie łamiesz zasad SOLID skoro musisz takie cuda robić. Moim zdaniem powinieneś mieć pewną klasę serwisową która dokonuje zmian parametrów, a wszystkie inne obiekty tylko z tego serwisu korzystają.

0

Tzn tak: mam sporo roznych klas. W nich sa wskazniki do jeszcze innych obiektow klas i sie robi takie jednokierunkowe drzewko. Na samym szczycie tego drzewka mam wlasciwie klase GUI (nie chodzi tu o dziedziczenie). I teraz z klasy na samym dole musze sie dostac do pola w GUI ustawianej przez jakas metode w klasie GUI. I tu na mysl mi przychodza klasy statyczne. Nie trzeba do nich miec wskaznikow, przekazywac ich itp.

2

I teraz z klasy na samym dole musze sie dostac do pola w GUI ustawianej przez jakas metode w klasie GUI

To się nazywa cieknące warstwy i jest bardzo złą praktyką. Obiekt NIGDY powinien odnosić się do niczego innego niż swoje własne pola i metody, oraz metody swoich pól. W skrócie jeśli w linijce masz więcej niż jedną kropkę/strzałkę to znaczy że z kodem jest źle. Absolutnie nie wolno pisać potworków w stylu:

x.getY().getZ().getV().getParent().getParent().setParameter(cośtam);

Bo to robi się enkapsulacje za pomocą obiektów i klas żeby jej potem tak nie łamać.
Co w takim razie wypadałoby zrobić? W całej hierarchii przygotowac odpowiednie metody, tzn będzie wtedy tylko

x.getY().setParameter(cośtam);
//a setParameter() w Y robi
getZ().setParameter(cośtam);

i tak dalej.
Nadal nie jest to eleganckie (bo błąd w projekcie jest już na etapie architektury) ale sensowniejsze.

Albo tak jak mówiłem zrobić jakis singletonowy serwis który te operacje wykonuje, o ile ma to jakiś sens, bo nie wiem o jakie operacje chodzi.

0

Wlasnie cieknacych warstw chce uniknac. Ale zobacz ze majac pola statyczne na te parametry moge sie do nich odwolac bardzo latwy sposob GUI::kolor. A w przypadku klikniecia np w button zmiany koloru ustawiam tylko GUI::setColor(red) (ewentualnie stworzyc osobna klase na tecparametry). Wiem ze to moze sie za bardzo kojarzy ze zmiennymi globalnymi rodem z C ale czy nie jest to najlogiczniejszy sposob? Co do bledu w architekturze to wydaje mi sie ze jest ok. Program ma teraz 3 istotne klasy (oczywiscie sie rozrasta): GUI (okno glowne), Ramka (pewien kontener w oknie) oraz Punkt (w Ramce sa dziesiatki obiektow Punkt). Strukturalnie to wyglada tak (w uproszczeniu - pseudokod)

class GUI extends Jwindow
{
   Ramka * ramka; //wskaznik na obiekt tego Frame'a
 //kolejne elementy interfejsu

   TextArea textarea; //jakis input na tekst
   String tekst; //tekst z powyzszego inputa
}

class Ramka extends Jframe
{
    Punkt *** punkt //tablica dwuwymiarowa ze wskaznikami na obiekt Punkt (taka siatka w Ramce)
}

class Punkt
{
// z tad chce sie dostac do stringa tekst
}

Dlatego wydaje mi sie ze najprosciej jest zrobic klase z polami statycznymi na wartosci z elementow GUI.

Ps przepraszam za notacje z roznych jezykow, to pseudokod

0

No to po kolei, czemu to co proponujesz jest złe:

  1. Łamie zasadę jednej odpowiedzialności bo te parametry powinny leżeć w osobnej klasie, szczególnie jeśli inne obiekty chcą coś z nimi robić.
  2. Związujesz sobie bardzo mocno obiekty ze sobą, co znów jest złamaniem kolejnej zasady SOLID -> Dependency inversion principle, bo polegasz tutaj na implementacji i na występowaniu pewnych pól, a powinieneś polegać jedynie na kontrakcje (interfejsie) do serwisu.
0

Ale sam program jest poprawny architektonicznie prawda? W takim wypadku ostatnie pytanie jak bys przekazal jakas wartosc do obiektu klasy Punkt z elementu GUI?

0

A z jakiej niby racji GUI miałoby cokolwiek robić z jakimś punktem? Mówies chyba że chcesz uniknąć cieknących warstw a pytasz właśnie o to jak zrobić takie przeciekanie. GUI jest na zupełnie innym poziomie abstrakcji niż Punkt i nie powinna istnieć między nimi żadna bezpośrednia komunikacja.
To tak jakbyś pisał soft dla samochodu i pytał jak to zrobić żeby kierowca za pomocą pokrętła na tablicy rozdzielczej mógł zmieniać napięcie na świecy...

0

Zapewne masz racje. Ale nadal nie wiem jak udostepnic te dane dla dla pozostalych klas ktore ich wymagaja a sa nizej w hierarchii. Pola statyczne nie, przekazywanie "wezykiem" rowniez nie, skonczyly mi sie pomysly. Wierze ze ten projekt do tej pory jest dobrze napisany :)

1

A jak przypuszczam ze nie jest bo klasy niżej w hierarchii NIE MOGĄ potrzebować pól klas wyżej w hierarchii. Jeśli potrzebują to ewidentnie ciekną ci warstwy, albo łamiesz zasadę jednej odpowiedzialności (bo trzymasz jakieś pola w miejscu gdzie ich być nie powinno).

0

Ok ja to rozumiem. Ale wyobraźmy sobie taką przyszłą sytuację że będę miał masę kontrolek, np kontrolkę odpowiedzialną za zmianę koloru obiektu klasy Punkt (obiekt ten to jakaś ramka np. 10x10pixeli) Ta kontrolka oraz metody odpowiedzialne za przechwytywanie eventów zanjduje się w klasie GUI odpowiedzialnej za wygląd itp. No i jest problem bo muszę pokolorować ten Punkt. Wciskam przycisk "Maluj" i wiem że nie mogę zrobić czegoś takiego :

//w GUI
ramka->punkt->maluj(wybrany_kolor)

bo mi zaczną cieknąć warstwy. Zgodzimy się że do tej pory jest OK, poprawny obiektowy kod. Jeżeli obiekt składa się z innych obiektów mamy w klasie referencje/wskaźniki do tych obiektów a gdy obiekt jest szczególnym typem innego, to wtedy jest dziedziczenie (za książką). Ja chyba wybrałem poprawnie - wskaźnik do obiektu Ramka w klasie GUI (przykład: Mieszkanie -> Kuchnia -> Stół | Okno (GUI) -> Ramka -> Punkt w ramce) i Punkt w klasie Board. Jedyne co muszę teraz rozwiązać to np. jeżeli wybiorę kolor tła dla Punktów z menu, to jak zmusić te punkty żeby wiedziały że się mają pokolorować, bez konstrukcji o których pisałem wcześniej. na razie wiem czego nie mogę robic ale nie wiem co i jak muszę.

Pozdrawiam

1

To zależy. Czy guzik powoduje pomalowanie wszystkich punktów? Wtedy:
ramka->malujPunkty(kolor)
Jeśli w jakiś sposób je chcesz wybierać to przekazujesz tam kolor oraz algorytm wyboru punktów.
Jeśli guzik powoduje pomalowanie jednego jedynego punktu, bo to taki dziwny guzik, to wtedy obiekt Akcji tego guzika powinien mieć referencje (wskaźnik) do punktu który maluje.

Chodzi o to żebyś nie tworzył takich sztywnych konstrukcji. Jak zrobisz
ramka->punkt->cośtam
to automatycznie sprawiasz że implementacja wymusza istnienie pola punkt w ramce. A co jeśli zmieni się trochę projekt i nagle ramka będzie miała w sobie jakieś pod-ramki z punkami?

0

Chodzi o to żebyś nie tworzył takich sztywnych konstrukcji. Jak zrobisz

ramka->punkt->cośtam

to automatycznie sprawiasz że implementacja wymusza istnienie pola punkt
w ramce. A co jeśli zmieni się trochę projekt i nagle ramka będzie
miała w sobie jakieś pod-ramki z punkami?

Dokładnie tak jak piszesz! Jeżeli mamy tylko te 2 warstwy (ramka -> punkt) to możemy napisać tak jak powiedziałeś ale

Jeśli guzik powoduje pomalowanie jednego jedynego punktu, bo to taki
dziwny guzik, to wtedy obiekt Akcji tego guzika powinien mieć referencje
(wskaźnik) do punktu który maluje

No i tu jest problem, bo jeżeli będzie, tak jak napisałeś, więcej warstw (bo np projekt się zmieni) np. ramka->subramka->punkt->subpunkt i będę chciał pomalować ten, jeden, konrektny punkt albo przekazać tam ten kolor to nie ma wyjścia i trzeba będzie zrobić wężyk ramka->subramka->punkt->subpunkt->pobierzWskaznikTegoSubpunktu(). Dobrze zrozumiałem?

1

To strasznie hipotetyczne ;] W realnym systemie gdybyś faktycznie miał coś takiego to ten punkt byłby w jakiś sposób specjalny i zapewne tworzony gdzieś "wysoko", może nawet trzymany w jakimś service locatorze albo wstrzykiwany przez IoC.

0

Ok, to ja kontynuuję. Postaram się unikać problemów o których pisałeś. na razie idzie całkiem dobrze. Dzięki

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