|
|
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
Page 3 of 5
Because the Java compiler implements the Flyweight pattern for strings, I can't show you how it's done. So, let's move on to another flyweight implemented in the Java APIs.
Swing comes with an exhaustive set of borders for its components, including line borders, titled borders, bevel borders, etc. Figure 3 shows an application that fits two panels with a bevel border.

Figure 3. Swing borders
You can implement component borders in numerous ways. The GOF book, for example, shows you how to implement them with the Decorator pattern (see page 175), but in Swing, they're implemented as flyweights for maximum performance. Additionally, Swing lets you instantiate a single border per component if you wish, but it also provides a border factory that creates flyweight borders so a single border can be shared among multiple components. Example 2, the listing for Figure 3's application, illustrates the use of that factory.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class Test extends JFrame {
public static void main(String[] args) {
Test test = new Test();
test.setBounds(20,20,250,150);
test.show();
}
public Test() {
super("Border flyweights");
JPanel panel = new JPanel(), panel2 = new JPanel();
Border border = BorderFactory.createRaisedBevelBorder();
Border border2 = BorderFactory.createRaisedBevelBorder();
panel.setBorder(border);
panel.setPreferredSize(new Dimension(100,100));
panel2.setBorder(border2);
panel2.setPreferredSize(new Dimension(100,100));
Container contentPane = getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(panel);
contentPane.add(panel2);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosed(WindowEvent e) {
System.exit(0);
}
});
if(border == border2)
System.out.println("bevel borders are shared");
else
System.out.println("bevel borders are NOT shared");
}
}
The preceding application's output is: bevel borders are shared, which means the two panels share a single border instance. Notice that BorderFactory.createRaisedBevelBorder() is somewhat of a misnomer because it doesn't actually create anything if a bevel border already exists in the factory.
Borders have a paintBorder() method that the border's component invokes when the component is painted. Here is that method's signature:
public void paintBorder(Component c,
Graphics g,
int x,
int y,
int width,
int height)
The arguments passed to paintBorder() represent a border's extrinsic state, namely, a component, a graphics object to draw in, and the border's bounds. Because
a border can be a flyweight, and therefore shared by multiple components, the border does not maintain that extrinsic state.
Swing tree nodes are excellent candidates for the Flyweight pattern. Consider Figure 4, which shows a Swing tree that acts as a file explorer.

Figure 4. Swing trees
As a testament to Swing's design, a file explorer like the one in Figure 4 is straightforward to implement. In fact, it's a mere 144 lines of code, blank lines and all. As a testament to the Flyweight pattern, that file explorer is fast. If you wish, you can download this article's source code and take the file explorer for a spin. If you do, explore some directories with a lot of files so you have a tree with many nodes like Figure 4 (note the scrollbar thumb's size). Then grab the scrollbar thumb and move it up and down as fast as you can. You'll see that performance is excellent.
Archived Discussions (Read only)