Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Make your apps fly

Implement Flyweight to improve performance

  • Print
  • Feedback

Page 4 of 5

Swing trees are blazingly fast because they use a single component for all nodes in the tree. That component is created by a tree cell renderer with the overly verbose TreeCellRenderer.getTreeCellRendererComponent() method, whose signature is listed below:

public Component getTreeCellRendererComponent(JTree tree,
                                              Object value,
                                              boolean selected,
                                              boolean expanded,
                                              boolean leaf,
                                              int row,
                                              boolean hasFocus)


By now, the sheer number of arguments to getTreeCellRendererComponent() should indicate to you that the component returned from the method is a flyweight. Like Swing borders, tree cell renderers are passed extrinsic state so the rendering component can be shared. The getTreeCellRendererComponent() method sets the component's properties depending upon the extrinsic state. For instance, for folders, getTreeCellRendererComponent() fits the component with a folder icon; if not, it uses a document icon.

As an aside, Swing tables render table cells in the same manner as Swing trees. One component represents all the cells for a single table, so Swing tables also have excellent performance.

So far I've detailed three Flyweight pattern examples in Java, but for you to understand the Flyweight pattern completely, let's implement a flyweight from scratch.

Roll your own!

The rest of this article implements a line flyweight similar to the one discussed at the beginning of this article. We'll explore that implementation in three steps. First, I implement an application that draws 10,000 lines without the aid of a line object, by simply painting repeatedly into a graphics context. Second, I implement a naive Line class that cannot be shared. Third, I turn that naive implementation into a flyweight. Figure 5 shows the line-drawing application.

Figure 5. Drawing lines with Swing

Drawing without line objects

Example 3 lists Figure 5's application.

Example 3. Drawing lines without line objects

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
public class Test extends JFrame{
   private static final Color colors[] = { Color.red, Color.blue,
                                           Color.yellow, Color.orange,
                                           Color.black,  Color.white };
   private static final int WINDOW_WIDTH=400,
                            WINDOW_HEIGHT=400,
                           NUMBER_OF_LINES=10000;
   public Test() {
      Container contentPane = getContentPane();
      contentPane.setLayout(new BorderLayout());
      
      JButton button = new JButton("draw lines");
      final JPanel  panel  = new JPanel();
      contentPane.add(panel,  BorderLayout.CENTER);
      contentPane.add(button, BorderLayout.SOUTH);
      setBounds(20,20,WINDOW_WIDTH,WINDOW_HEIGHT);      
      button.addActionListener(new ActionListener() {
         public void actionPerformed(ActionEvent event) {
            Graphics g = panel.getGraphics();
            for(int i=0; i < NUMBER_OF_LINES; ++i) {
               g.setColor(getRandomColor());
               g.drawLine(getRandomX(), getRandomY(), 
                          getRandomX(), getRandomY());
            }
         }
      });
   }
   public static void main(String[] args) {
      Test test = new Test();
      test.show();
   }
   private int getRandomX() {
      return (int)(Math.random()*WINDOW_WIDTH);
   }
   private int getRandomY() {
      return (int)(Math.random()*WINDOW_HEIGHT);
   }
   private Color getRandomColor() {
      return colors[(int)(Math.random()*colors.length)];
   }
}


The preceding application creates a window with two panels. The application draws lines with random colors, locations, and lengths into the top panel when you click on the button in the bottom panel. The graphic context's drawLine() method draws those lines.

  • Print
  • Feedback

Resources