Преимущества для вложенных классов для слушателей в графических интерфейсах

Для проектов с приличным размером мне сказали, что когда у вас есть классы, расширяющие JPanels, лучше всего использовать вложенные классы для реализации слушателей. Например, у меня может быть класс FactoryScreen, который расширяет JPanel и имеет вложенный класс FactoryScreenBrain, который реализует все необходимые прослушиватели.

Я никогда не мог получить хорошее объяснение конкретных преимуществ или недостатков для инкапсуляции моих классов таким образом, и до сих пор всегда были только классы, которые расширяют JPanel и реализуют слушателей. Может ли кто-нибудь дать мне некоторые рекомендации по этому поводу?

Ответ 1

Наличие внутренних классов для ваших слушателей делает цель всех этих слушателей очень ясной. Он также может иногда избегать многих, если проверки за счет немного большего количества кодировок.

Если у вас есть панель

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
    }

очень сложно точно увидеть, что происходит в вашем actionPerformed, потому что он обрабатывает сразу столько разных событий. Наличие панели:

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
        }
    }

Теперь, если у вашего таймера есть проблема, вы можете легко идентифицировать класс с проблемой.

Еще важнее, в широком смысле, это делает ваш код более читаемым. Если кто-то хочет работать над этим классом, и им нужно исправить обработку событий таймером, им не нужно искать через ifs, чтобы найти деталь с логикой таймера.

Ответ 2

Я думаю, что что-то лучше, чем класс, расширяющий Swing Component и реализующий слушателя, поскольку он дает классу слишком много разрозненных обязанностей и устанавливает один для создания ужасных слушателей коммутационной панели. Я пытаюсь использовать анонимные внутренние слушатели, которые вызывают методы из отдельного класса управления. Таким образом я разделяю обязанности и могу более легко тестировать поведение каждого класса в изоляции.

Хороший вопрос, кстати.

Ответ 3

Если вы расширяете компонент и реализуете один или несколько слушателей, возникает соблазн добавить слушателя в конструктор. Это потенциально предоставляет ссылку на неполностью сконструированный объект, иногда называемый который избежал этого. Работа исключительно над EDT снижает риск; но анонимный внутренний класс может еще больше уменьшить его. Проблемы с отражением или косвенная экспозиция остаются.