[Java] Przekazywanie opcji programu - wzorzec projektowy?

0

witam, piszę w Javie, pytanie jednak mam dość ogólne.

Czy istnieje uznane rozwiązanie opisujące, jak przechowywać w programie i udostępniać obiektom (przekazywać) opcje aplikacji?

Wyobraźmy sobie program z interfejsem graficznym, gdzieś w menu jest pozycja "Opcje". Otwiera ona panel z ustawieniami, użytkownik coś tam modyfikuje, potem wciska OK i opcje się uaktualniają. Zanim otwarto panel, już były jakieś wartości domyślne. Więc istnieje pewnie jakiś obiekt przechowujący opcje (ja tak robiłem do tej pory).

Chodzi mi o to, jak przekazywać ten obiekt, albo jak tego unikać?
Załóżmy, że to program rysujący bibliotekę. Obiekt ramowy aplikacji (ten, w którym jest main() ) ma referencję do opcji. Tworzy on np. obiekt "biblioteka", "biblioteka" tworzy "półkę", "półka" tworzy "książkę", "książka" tworzy swój "grzbiet". Dajmy na to, że grzbiet musi umieć się narysować i robi to na podstawie opcji (np. prawdopodobieństwo wyboru koloru, domyślna czcionka itp.).

ROZWIĄZANIA (żadne nie jest dobre):

  1. GLOBALNE: opcje globalne - odpada w przedbiegach, nawet nie wiem, czy Java na to pozwala...

  2. STATYCZNE: zapisywanie dla każdej klasy opcji, które jej dotyczą w polach statycznych tej klasy przed pierwszym użyciem. Dobre, bo każda klasa pamięta tylko to, co jej dotyczy. Ale co, gdy mamy wiele bibliotek, wiele półek, a wszystkie mają być różne (z różnymi opcjami)?

  3. ŁAŃCUCH: z głównego obiektu opcje są przekazywane do biblioteki, z biblioteki do półki, z półki do książki itd. Wady: łańcuch bywa bardzo długi (czasem po kilkanaście ogniw), a opcje potrzebne tylko w ostatnim - wszystkie pośrednie obiekty (nawet takie, które nie potrzebują żadnych opcji) są więc "zarażane" uzależnieniem od obiektu opcji, tzn. muszą przechowywać referencje do opcji, których nie potrzebują i które ich nie dotyczą. Robi się z tego straszny balast (bo takie sytuacje się namnażają), bałagan i zaciemnia to kod. Potem jest tak, że prawie każda moja klasa przyjmuje w konstruktorze parametr ProgramOptions opt. Takie coś skutecznie uniemożliwia powtórne użycie kodu i wydaje mi się ogłupiające, ale nie wymyśliłem nic lepszego.
    Po drugie w programie może być 20 000 obiektów, a każdy ma referencję. Nie da się tego szybko aktualizować, ani mieć pewności, która referencja jest aktualna, a która nie. Poza tym wtedy wszystko staje się powiązane ze wszystkim - nie da się narysować diagramu UML moich programów.

Ktoś zna jakieś skuteczne rozwiązanie tego problemu? To chyba problem zupełnie typowy, większość aplikacji ma jakieś opcje... Tymczasem google w kółko pokazują mi do znudzenia Adater, Bridge, Facade, Decorator, jak zgraną płytę...

0

Co do globalnych to trzeba do tego podejść trochę inaczej niż np. w C, ale da się.
Po pierwsze: Singleton wzorzec przekleństwo, ale jeżeli zrobisz sobie coś takiego:

public static void main(String[] arg){
    Context.loadAndInit();
}

I klasa Context będzie singletonem to później w dowolnym miejscu aplikacji:

Context applicationConntext = Context.getContext();

nie będzie błędnym użyciem wzorca.

Co do statycznych to głupia metoda o ile zrobisz to wprost. Za dużo dodatkowego, "magicznego" kodu do utrzymania. Można jednak podejść do tego trochę inaczej. Za pomocą wcześniej wspomnianego Context i AspectJ napisać sobie aspekt, który będzie wykonywany "post-construct" i będzie wstrzykiwał konfigurację do obiektu. Względnie zamiast tworzyć obiekty bezpośrednio użyć fabryki/ wzorca prototyp.

Łańcuch to rozsądne, ale tylko w przypadku gdy jest krótki. Inaczej rzeczy wysokopoziomowe zaczynają mieszać się z niskopoziomowymi.

Tyle w temacie składowania konfiguracji i jej przekazywania nowym obiektom.

Problem numer dwa czyli aktualizacja kontekstu. Wzorzec obserwator wydaje się być rozsądny, ale... po pierwsze jeżeli będzie dużo wywołań modyfikujących to całość się zapcha. Po drugie każdy obiekt, który używa kontekstu będzie musiał jakoś sprawdzać czy w trakcie jakiejś czynności nie nastąpiła zmiana stanu kontekstu. To że jest dużo referencji to nie przeszkadza, bo zmieniasz stan obiektu, a ten jest "przesłonięty" przez wspólną referencję, zatem aktualizując obiekt jednocześnie wszystkie obiekty go używające będą mogły pobrać jego nowy stan. Jednocześnie jeżeli jakiś obiekt pobrał sobie coś z kontekstu i przechowuje to lokalnie to aktualizacja wpisu w kontekście spowoduje, że obiekt dostanie stary stan. I znowu w tym momencie wzorzec obserwator i powiadamianie obiektów, że muszą się zaktualizować.
Na to nie ma dobrego patentu. Java nie ma mechanizmu pozwalającego na zliczanie referencji, a implementacja tego rozwiązania jest inna w każdym JVM.

0

http://www.vogella.de/articles/Eclipse/article.html (Eclipse RCP)
http://www.vogella.de/articles/EclipsePreferences/article.html Mozesz popatrzec jak to robia w IBM ;)

http://www.vogella.de/articles/JavaPreferences/article.html#preferenceusage (java.util.prefs.Preferences)

Obstawil bym przy Singeltonie. Jest to bezpieczne, bo zazwyczaj nie majstrujesz przy ustawieniach w trakcie wielowatkowych wywolan. Jesli jest inaczej, to sproboj w miare mozliwosci oprogramowac to w taki sposob, aby ustawienia byly modyfikowane tylko jesli na ich podtawie nie wykonuje sie jakichs operacji.

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