Pytanie Zalety zagnieżdżonych klas dla słuchaczy w GUI


W przypadku projektów o zwymiarowanych rozmiarach powiedziano mi, że jeśli masz klasy rozszerzające JPanels, najlepszą praktyką jest używanie klas zagnieżdżonych do implementacji słuchaczy. Na przykład mogę mieć klasę FactoryScreen, która rozszerza JPanel i ma zagnieżdżoną klasę FactoryScreenBrain, która implementuje wszystkie niezbędne detektory.

Nigdy nie byłem w stanie uzyskać dobrego wytłumaczenia dla konkretnych korzyści lub wad, które mogłyby obejmować moje zajęcia w ten sposób, i do tej pory zawsze miałem tylko zajęcia, które zarówno rozszerzają JPanel, jak i wdrażają słuchaczy. Czy ktoś może mi doradzić?


11
2018-02-22 23:08


pochodzenie


Niepotrzebnie rozszerzające JPanel (lub JFrame lub Thread) nie jest najlepszą praktyką. Ale programowanie GUI i dobra praktyka nie spotykają się - Tom Hawtin - tackline


Odpowiedzi:


Posiadanie klas wewnętrznych dla słuchaczy sprawia, że ​​cel tych wszystkich słuchaczy jest bardzo jasny. Może też czasami uniknąć wielu, jeśli kontrole kosztem nieco więcej kodowania.

Jeśli masz panel

public class MyPanel extends JPanel implements ActionListener
...
    button1.addActionListener(this);
    button2.addActionListener(this);
    checkbox1.addActionListener(this);
    timer3.addActionListener(this);

    public void actionPerformed(ActionEvent e)
    {
        if(e.getSource() == button1)
        else...
        ... //potentially many elses
    }

bardzo trudno jest zobaczyć, co dokładnie dzieje się w Twoim działaniu, ponieważ obsługuje on tak wiele różnych zdarzeń naraz. Posiadanie panelu:

public class MyPanel extends JPanel
...
    button1.addActionListener(new ButtonListener());
    button2.addActionListener(new ButtonListener());
    checkbox1.addActionListener(new CheckBoxListener());
    timer3.addActionListener(new TimerListener());

    private class TimerListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            //do stuff related only to timers
        }
    }

Teraz, jeśli czasomierz ma problem, możesz łatwo zidentyfikować klasę z problemem.

Co ważniejsze, na wielką skalę, czyni twój kod bardziej czytelnym. Jeśli ktoś inny chce pracować z tą klasą i musi naprawić obsługę zdarzeń za pomocą timera, nie musi przeszukiwać twoich ifs, aby znaleźć część z logiką timera.


8
2018-02-22 23:41





Sądzę, że wszystko jest lepsze, niż gdyby klasa rozszerzyła Swing Component i zaimplementowała słuchacza, ponieważ daje on zbyt wiele różnorodnych obowiązków i przygotowuje go do tworzenia przerażających słuchaczy przełączników. Próbuję korzystać z anonimowych wewnętrznych detektorów, które wywołują metody z oddzielnej klasy kontrolnej. W ten sposób podzielę się obowiązkami i łatwiej będzie przetestować zachowanie każdej klasy w izolacji.

Dobre pytanie, nawiasem mówiąc.


6
2018-02-22 23:17



Tak. Rozdzielenie obaw to wielka wygrana. Zagnieżdżona (lub anonimowa) klasa wewnętrzna ma jedno i tylko jedno zadanie do wykonania. Sprawia, że ​​śledzenie całego jego zachowania jest bardzo łatwe. Jeśli masz panel, na którym znajduje się kilkanaście obiektów wywołujących jedną metodę actionPerformed, to ta metoda jest większa, trudniejsza do zrozumienia lub utrzymania. Jeśli na przykład zmienisz tę metodę w jednym celu, ryzykujesz przypadkowym wpływem na inne obowiązki obsługiwane tą metodą. - Kaffiene
Dziękuję za komentarz i ewentualnie za podwyższenie. Jeśli to byłeś ty, musisz mnie popchnąć ponad 3000. Grats! :) - Hovercraft Full Of Eels


Jeśli rozszerzysz komponent i zaimplementujesz jednego lub więcej detektorów, to kusi dodać detektora (ów) do konstruktora. To potencjalnie naraża odniesienie do nie w pełni skonstruowanego obiektu - czasami nazywanego uniknęli tego. Praca wyłącznie nad EDT zmniejsza ryzyko; ale anonimowa klasa wewnętrzna może ją jeszcze bardziej zmniejszyć. Problemy z refleksji lub pośrednie narażenie pozostawać.


2
2018-02-23 02:11



Nie jestem pewien, czy użycie anonimowej klasy wewnętrznej rozwiązuje problem. Później w dół strony ibm.com/developerworks/java/library/j-jtp0618.html#3 opisuje, jak anonimowa klasa wewnętrzna może nadal podlegać warunkom wyścigu, jeśli podklasa opiera się na zdarzeniach. Jedyny sposób, w jaki mogę naprawdę tego uniknąć, może sprawić, że twoja klasa GUI stanie się ostateczna (co jest w niektórych przypadkach wykonalne), ale link nie wyjaśnia innych metod rozwiązania tego ... - donnyton
Słuszna uwaga; to nie jest panaceum. Jak zauważa Joshua Bloch: "Zaprojektuj i udokumentuj dziedziczenie lub zakazaj tego". - trashgod
Chciałbym zrozumieć głosowanie oddane, więc mogę wyjaśnić odpowiedź. - trashgod