On-Line Библиотека www.XServer.ru - учебники, книги, статьи, документация, нормативная литература.
       Главная         В избранное         Контакты        Карта сайта   
    Навигация XServer.ru






 

Обработка событий с помощью анонимных внутренних классов

При разработке графического интерфейса пользователя (GUI) в Java много работы уходит на настройку обработчиков событий для каждого компонента, события которого вы желаете отследить. Обычно это включает в реализацию класса один или несколько обработчиков событий и перегрузку необходимых методов этих компонентов.

Если у вас много компонентов, то управление этими обработчиками событий часто становится большой головной болью. Например, рассмотрим Java апплет, который имеет несколько кнопок, каждая из которых при нажатии исполняет уникальную задачу. Для каждой кнопки мы должны назначить ActionListener, чтобы обработать щелчки мыши пользователя, и перегрузить метод actionPerformed.

При наличии в нашем классе приложения реализации ActionListener и перегрузки метода actionPerformed мы обрабатываем все события кнопки в пределах нашего апплета. К сожалению, так как каждая кнопка отслеживается тем же самым ActionListener, наш actionPerformed метод должен выполнять несколько сравнений, чтобы определить, какая кнопка была нажата. Обычно это исполняется гадким switch или инструкцией if/else, как показано ниже, и это действительно не очень хороший объектно-ориентированный подход.

import java.applet.*;

import java.awt.*;

import java.awt.event.*;


public class
 Testing extends Applet implements
 ActionListener
{
  TextField txt1 = new TextField(10);
 
 Button btn1 = new Button("Button1");
  
Button btn2 = new Button("Button2");
  
Button btn3 = new Button("Button3");
  
Button btn4 = new Button("Button4");

  
public void init()

 {
   add(txt1);
   add(btn1);
   add(btn2);
   add(btn3);
   add(btn4);
   
btn1.addActionListener(this);
  
 btn2.addActionListener(this);
   
btn3.addActionListener(this);
  
 btn4.addActionListener(this);
  }

  
public void 
actionPerformed(ActionEvent e)
  {
    if
(e.getActionCommand().equals("Button1"))
    
{
     txt1.setText("Button1 clicked");
    }
    
else if
(e.getActionCommand().equals("Button2"))
    
{
     txt1.setText("Button2 clicked");
    }
    
else if
(e.getActionCommand().equals("Button3"))
    
{
     txt1.setText("Button3 clicked");
    }
    
else 
if(e.getActionCommand().equals("Button4"))
    
{
     txt1.setText("Button4 clicked");
    }
  }
}

Другой подход состоит в том, чтобы создать для каждого компонента отдельный класс, единственная цель которого состоит в том, чтобы обработать события этого компонента. Этот подход лучше в том, что он более объектно-ориентирован, однако создает целую связку новых файлов класса, за которыми вы должны следить. К тому же, обрабатывая события в отдельном классе вы теряете доступ к любым полям апплета. Кроме того использование этого подхода также увеличивает количество HTTP запросов, которые должен исполнить броузер, чтобы загрузить апплет.

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

Анонимные классы - классы без имени, образующиеся не только конструктором, но и непосредственно определением класса. Если вы никогда не использовали анонимные классы прежде, тогда синтаксис может показаться вам немного неуклюжим.

import java.applet.*;

import java.awt.*;                                          
 
import java.awt.event.*;                      
               
public 
class Testing extends
 Applet                          
{                                                            
  TextField txt1 = new TextField(10);                        
  Button btn1 = new Button("Button1");                       
  Button btn2 = new Button("Button2");                       
  Button btn3 = new Button("Button3");                       
  Button btn4 = new Button("Button4");                       
                                                             
  public void init()                                         
  {                                                          
   add(txt1);                                                
   add(btn1);                                                
   add(btn2);                                                
   add(btn3);                                                
   add(btn4);                                                
                                                             
   /* Создаём анонимный внутренний класс для каждого ActionListener */
                                                             
   btn1.addActionListener(new ActionListener()               
   {                                                         
    public void actionPerformed(ActionEvent e)               
    {                                                        
     txt1.setText("Button1 clicked");                        
    }                                                        
   });                                                       
                                                             
   btn2.addActionListener(new ActionListener()               
   {                                                         
     public void actionPerformed(ActionEvent e)              
     {                                                       
       txt1.setText("Button2 clicked");                      
     }                                                       
   });                                                       
                                                             
   btn3.addActionListener(new ActionListener()               
   {                                                         
     public void actionPerformed(ActionEvent e)              
     {                                                       
       txt1.setText("Button3 clicked");                      
     }                                                       
   });                                                       
                                                             
   
btn4.addActionListener(new ActionListener()               
   
{                                                         
     
public void 
actionPerformed(ActionEvent e)              
     
{                                                       
       
txt1.setText("Button4 clicked");                      
     }
                                                       
   });                                                       
                                                             
  }                                                          
                                                             
}

Каждый компонент теперь имеет свой собственный actionListener, здесь нет вредных инструкций if/else. В самом верху вся обработка событий централизована в пределах отдельного класса, делающего этот класс намного проще для управления. В случае добавления к этому классу нового компонента, события которого надо обрабатывать, просто требуется создать новый анонимный обработчик событий.

В качестве примечания: JBuilder - одна из немногих интегрированных сред разработки, которая по умолчанию использует анонимные внутренние классы при определении обработчиков событий. Например при использовании проектировщика GUI, если вы сделаете двойной щелчок на компоненте Кнопка, то автоматически сгенерируется код для анонимного внутреннего класса, действующего как обработчик событий этого компонента.



Языки программирования: разное