Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Java Tip 75: Use nested classes for better organization

Express coupling between components in Java subsystems with top-level nested classes

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Page 2 of 3

// SlateModel.java
import java.awt.Shape;
 
public interface SlateModel { 
    // Listener management 
    public void addSlateModelListener(SlateModelListener l); 
    public void removeSlateModelListener(SlateModelListener l); 
    // Shape repository management, views need notification 
    public void addShape(Shape s); 
    public void removeShape(Shape s); 
    public void removeAllShapes(); 
    // Shape repository read-only operations 
    public int getShapeCount(); 
    public Shape getShapeAtIndex(int index); 
}
// SlateModelListener.java
import java.util.EventListener;
public interface SlateModelListener extends EventListener { 
    public void slateChanged(SlateModelEvent event); 
} 
// SlateModelEvent.java
import java.util.EventObject;
public class SlateModelEvent extends EventObject { 
    public SlateModelEvent(SlateModel model) { 
        super(model); 
    }
}


(The source code for DefaultSlateModel, the default implementation for this model, is in the file before/DefaultSlateModel.java.)

Next, we turn our attention to Slate, a view for this model, which forwards its painting task to the UI delegate, SlateUI:

// Slate.java
import javax.swing.JComponent;
public class Slate extends JComponent implements SlateModelListener { 
    private SlateModel _model; 
    public Slate(SlateModel model) { 
        _model = model; 
        _model.addSlateModelListener(this); 
        setOpaque(true); 
        setUI(new SlateUI()); 
    } 
    public Slate() { 
        this(new DefaultSlateModel()); 
    } 
    public SlateModel getModel() { 
        return _model; 
    } 
    // Listener implementation 
    public void slateChanged(SlateModelEvent event) { 
        repaint(); 
    } 
} 


Finally, SlateUI, the visual GUI component:

// SlateUI.java
import java.awt.*;
import javax.swing.JComponent;
import javax.swing.plaf.ComponentUI;
public class SlateUI extends ComponentUI { 
    public void paint(Graphics g, JComponent c) { 
        SlateModel model = ((Slate)c).getModel(); 
        g.setColor(c.getForeground()); 
        
        Graphics2D g2D = (Graphics2D)g;
        for (int size = model.getShapeCount(), i = 0; i < size; i++) { 
            g2D.draw(model.getShapeAtIndex(i)); 
        }
    }
} 


After: A modified example using nested classes

The class structure in the example above does not show the relationship between the classes. To mitigate this, we've used a naming convention that requires all related classes to have a common prefix, but it would be clearer to show the relationship in code. Furthermore, developers and maintainers of these classes must manage three files: for SlateModel, for SlateEvent, and for SlateListener, to implement one concept. The same is true with managing the two files for Slate and SlateUI.

We can improve things by making SlateModelListener and SlateModelEvent nested types of the SlateModel interface. Because these nested types are inside an interface, they're implicitly static. Nonetheless, we've used an explicit static declaration to help the maintenance programmer.

Client code will refer to them as SlateModel.SlateModelListener and SlateModel.SlateModelEvent, but this is redundant and unnecessarily long. We remove the prefix SlateModel from the nested classes. With this change, client code will refer to them as SlateModel.Listener and SlateModel.Event. This is short and clear and does not depend on coding standards.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (1)
Login
Forgot your account info?

goodBy Anonymous on November 4, 2009, 6:29 amgood

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources