Chapter 20. BLOG: INNER CLASSES AND EVENT HANDLERS

     

Beware when using inner classes, anonymous inner classes in particular. They are the subjects of much debate within the Java community. Developers who don't like their use say they break encapsulation ”one of the key principles of object-oriented programming ”and that they're hard to read and difficult for beginners to understand.

Developers who promote their use during late night local television shows point to their convenience and elegance . You need to know about them to read and write Swing application code. But in general, you don't need them, and your code is probably clearer and more flexible without them.

My rule is this: Use anonymous inner classes to handle actions and events. Don't use the other kind of inner classes. I think that's where the true confusion can come in, given how inner and outer classes share their members .

But anonymous inner classes solve the problem of the Monolithic Switch Block ”an antipattern familiar to coders throughout the land. Come on. I know you've done it. The first step to getting help is admitting you have a problem .

Whenever you see code like this, where the frame itself implements the ActionListener interface .

 

 public class MyGUI extends JFrame implements           ActionListener {    protected JButton btnSave; protected JButton btnCancel; //and so on //have to implement this guy because he //showed up with the ActionListener interface    public void actionPerformed(ActionEvent event) { String command = event.getActionCommand(); //use giant if/else block to determine //who fired this event       if (command.equals("Save...")) {          // do something: handleSave();       } else if(command.equals("Cancel")) {          //and so on... private void handleSave() { //do work here } 

you know there's too much Liquid Drano in the code designer's latt . This is not good object-oriented design. In general, this kind of construct can grow fairly large, and changes in one place in the code often require changes in another part of the code. Moreover, if/else blocks require the runtime to test the conditions, and this means that your app could slow down the larger it gets.

Why run a bunch of tests you don't have to?

The same deal implemented with an anonymous inner class would look like this:

 

 //look ma! no "implements ActionListener" //on the class! public class MyGUI extends JFrame { createGUI() { //create the buttons    JButton btnSave = new JButton("Save..."); JButton btnCancel = new JButton("Cancel"); //add action handlers btnSave.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //do something for save } }); btnCancel.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //do something for cancel } }); //... 

Anonymous inner classes solve some problems: The code is always where it should be, and you'll get better performance. It is probably polite to seriously limit the amount of code you put into an anonymous inner class if you can. Of course, you gotta do what you gotta do. But if you are going to put a lot of code into an event handler, you should just collect the data in the ActionListener, and then start a new thread inside it to do your work. Otherwise, your GUI will be frozen waiting for your ActionListener to get done.

Following is an example of how to start a new Thread in your ActionListener, which makes your GUI more responsive . It also delegates the actual work of the action to a handler, and does not attempt to do all of the work in the GUI class itself.

 

 JButton btnSearch = new JButton("Search"); btnSearch.addActionListener(new ActionListener() {         public void actionPerformed(ActionEvent e) {             Runnable runner = new Runnable() {                 public void run() {                                     try { ArrayList results = searchController.search();         createAndShowResultsPanel(results);                      } catch (BandSException bse) {                          //handle                      } catch (Exception ex) {                          ex.printStackTrace();                          //handle                      }                  }              };              Thread t = new Thread(runner);              t.setName("Search Thread");              t.start();          }     }); 

We call a controller (which I assume above we already have a reference to) as a delegate to do the work. This is the way you will usually want to handle button clicks and such ”it separates the GUI (code that creates the user view) from the business logic.



Java Garage
Java Garage
ISBN: 0321246233
EAN: 2147483647
Year: 2006
Pages: 228
Authors: Eben Hewitt

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net