2011-05-17 16 views
6

Piszę mały serwer sieciowy, i to wymaga pliku konfiguracyjnego z różnymi rodzajami różnych opcji: ile wątków do uruchomienia, jakie oferty klasy, które każde rozszerzenie pliku, który plik do wyświetlenia domyślnie i tak dalej i tak dalej. Aby to przedstawić, parsuję plik konfiguracyjny do obiektu Configuration, który zawiera wszystkie te ustawienia, a klasa główna przechowuje ten obiekt.
Jednak dane konfiguracyjne są wymagane na prawie każdym poziomie serwera - klasy w ramach klas ...Udostępnianie konfiguracji dla wszystkich klas

Moje pytanie brzmi, jaka jest najlepsza praktyka do wykorzystania tutaj? Czy powinienem podać config jako parametr dla wielu klas i przekazywać go w jedną i drugą stronę? Czy powinienem zrobić singleton? Czy istnieje inne rozwiązanie, którego nie widzę?

Odpowiedz

0

Zdecydowanie uczynię z klasy posiadacza konfiguracji Singleton! To klasyczny przypadek użycia dla instancji Singleton.

1

Stworzenie singletonu wydaje się rozsądnym rozwiązaniem. Myślę, że byłoby błędem przekazywać konfigurację jako parametr do innych klas konstruktorów lub wywołań metod, ponieważ spowoduje to zanieczyszczenie argumentów metody i sprawi, że będą niepotrzebnie skomplikowane.

Jeśli zdecydujesz się na singleton, to polecam opracowanie mechanizmu, dzięki któremu możesz wstrzyknąć nowe instancje config do klasy singleton, tak aby singleton nie sprawiał, że twoje testy były bardzo trudne do uruchomienia.

1

Przekazywanie instancji o numerze Configuration powoduje niepotrzebne zagracanie kodu. Singleton to dobry pomysł lub dodaj klasę Manager, która zapewnia wszystkie zasoby udostępnione, takie jak dane konfiguracyjne.

Jeśli pójdziesz do Singleton, należy rozważyć wdrożenie wzoru ENUM:

public enum Config{ DATA; 

    private int value1; 
    private int value2; 
    private int value3; 
    public load(File configFile) { 
    // some magic to store the values 
    } 
    public int getValue1() {return value1;} 
    public int getValue2() {return value2;} 
    public int getValue3() {return value3;} 
} 

Można go używać wszędzie w kodzie:

int property = Config.DATA.getValue1(); 
1

Jeśli robisz to w Javie, chciałbym umieść całą konfigurację w Spring, a następnie użyj parametru Application Context, aby sprawdzić ustawienia lub po prostu wprowadź je do swoich ziaren. Spring przoduje w tego typu rzeczach.

1

Mamy właściwości ustawione jako właściwości systemu. Dostęp do nich uzyskuje klasa SystemProperties.
Ta klasa to final z prywatnym konstruktorem, dostęp do właściwości odbywa się wyłącznie za pomocą metod statycznych, więc technicznie jest to Singleton. Sam jest zawarty w commons.jar, od czego zależy każdy inny projekt.

Nie trzeba niczego przekazywać, ponieważ ustawienia są dostępne bezpośrednio tam, gdzie są potrzebne.

+0

Może to zostać złamane, gdy na serwerze zostanie zainstalowana więcej niż jedna aplikacja internetowa. –

+0

@Aaron Digulla - z pewnością. Może nawet włamać się na własną rękę, jeśli ktoś ustawi właściwość na niewłaściwą wartość. Jedynym zabezpieczeniem są raczej długie i specyficzne nazwy właściwości. W naszej aplikacji jest wiele rodzajów właściwości, a podejście do właściwości systemu jest stosowane do najbardziej dynamicznych. Następnie są wdrożone właściwości jako powiązane XML, niektóre właściwości w Manifestie, a także niektóre właściwości zakodowane w ostatecznych klasach jako statyczne statki publiczne. I IMHO istnieją uzasadnione powody, aby korzystać z każdego z podejść. Po prostu nie dla wszystkiego, co to jest – kostja

3

Użyj Guice! Guice to struktura zależności od wtrysku, która skutecznie zastępuje użycie nowego słowa kluczowego. Możliwość zdefiniowania swoich obiektów powiązania w module tak:

A potem, zamiast newing się WebServer bezpośrednio, wystarczy zapytać Guice to zrobić dla Ciebie:

WebServer ws = Guice.createInjector(yourModule).getInstance(WebServer.class); 

Który będzie magicznie tworzyć MySpecificWebServerImplementation dla Ciebie.Jeśli MySpecificWebServerImplementation jest zdefiniowany następująco:

public class MySpecificWebServerImplementation { 
    @Inject 
    public MySpecificWebServerImplementation(Configuration configuration) { 
    } 
} 

Następnie MySpecificWebServerImplementation zostanie automatycznie ze względu na konfigurację i nie trzeba się martwić o przepuszczenie go dookoła.

+0

+1, jest nieco bardziej nowoczesne podejście DI w porównaniu ze starym szkolnym wzorem Singleton – Frank

0

Konfiguracja nie, ale dobrze jest mieć jeden obiekt singletonowy ServerManager. Zbyt wiele obiektów dostępnych globalnie jest trochę zagmatwanych. Konfiguracja powinna być własnością "komponentu":

ServerManager.getServerManager.getConfigurationComponent(Configuration.class); 

Menedżer serwerów powinien utworzyć i odczytać obiekt konfiguracyjny w momencie rozpoczęcia. Zapisz i zamknij przed wyjściem.

Jeśli używasz go więcej niż jeden raz w dowolnym magazynie klasy jako prywatne pole końcowe.

2

Mimo, że Singletons nie są już faworyzowane przez wielu specjalistów z różnych powodów - uważam, że nadal istnieje dobry przypadek użycia Ssingleton.

Jednak - zadaj sobie pytanie, czy wymagania serwera sieciowego wymagają jednej wspólnej konfiguracji dla wszystkich aspektów serwera. A jeśli tak, to jak szybko mogą one ulec zmianie? Na przykład - powiedzmy, że Twój serwer obsługuje 3 witryny. A teraz jesteś proszony o nałożenie ograniczeń przepustowości na jedną z nich - jak to skonfigurować?

Naprawdę faworyzuję dobry singleton - chociaż musisz mieć na uwadze cały problem z bezpieczeństwem wątków podczas inicjowania go w środowisku wielowątkowym (Chociaż brzmi to tak, jakbyś nie miał tego problemu, ponieważ nie będziesz mieć wielu nici przed inicjalizacji.

Należy pamiętać, że singletons żyć w ClassLoader a jeśli masz wiele ClassLoader s (na przykład dla każdego .war załadować) trzeba będzie wiele kopii tego „Singleton”.

rozważyć wszystkie aspekty twojego serwera, a jeśli to naprawdę proste - A Singleton Masz dużo bólu głowy - i sprawisz, że kod będzie dużo łatwiejszy do utrzymania i czytelny. Jak już wspomniano w jednej lub dwóch odpowiedziach - wtrysk zależności jest dobrą alternatywą dla Singleton s - pomagają one w tworzeniu JUnitów.

Jedna uwaga na temat JUnit, rozumiem (nie próbował go jeszcze), że Mockit może zezwolić, aby zastąpić rzeczywistą realizację podczas testu, więc nadal można tworzyć różne testów JUnit dla różnych scenariuszy bez modyfikowania Singleton być testowalnym.

+0

czy mógłbyś rozwinąć swoje stwierdzenie, że "Singletonowie nie są dłużej faworyzowani przez wielu profesjonalistów z różnych powodów"? Nie jestem pewien, czy podążam za tobą ... – mre

+0

@stupahsmaht - Wielu programistów odnosi się do 'Singleton' jako' antipattern', co oznacza coś, czego nie powinieneś robić.Jeśli używasz google "singleton antipattern", możesz znaleźć wiele odnośników do niego na wielu blogach. – RonK

Powiązane problemy