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

Take control with the Proxy design pattern

The Proxy design pattern substitutes a proxy for an object, making your apps more efficient

  • Print
  • Feedback

Page 4 of 6

Proxy.newProxyInstance() takes three arguments: the class loader that loaded the real subject, a list of interfaces implemented by the real subject, and a reference to an invocation handler.

Every time you invoke a proxy's method, the proxy calls its invocation handler's invoke() method. The proxy passes itself to the invoke() method, along with a reference to the proxy's method and its list of arguments. In the preceding code, SimpleInvocationHandler.invoke() invokes the specified method on the real subject. Here's the output of the application listed in Example 5:

Before Calling doSomething
Inside Method AClass.doSomething()
After Calling doSomething


Image-icon proxy, revisited

Example 6 shows how you can use the JDK's built-in support for the Proxy pattern to reimplement the image-icon proxy listed in Example 3:

Example 6. Image-icon proxies, revisited

import java.lang.reflect.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
// This class tests a virtual proxy, which 
// delays loading an expensive resource (an icon) until that 
// resource is needed.
public class VirtualProxyTest extends JFrame {
   private static String IMAGE_NAME = "mandrill.jpg";
   private static final int IMAGE_WIDTH = 256, IMAGE_HEIGHT = 256,
                                SPACING = 5,        FRAME_X = 150,
                                FRAME_Y = 200, FRAME_WIDTH = 530, 
                           FRAME_HEIGHT = 286;
   private ImageIcon imageIcon = null;
   private Icon imageIconProxy = null;
   static public void main(String args[]) {
      VirtualProxyTest app = new VirtualProxyTest();
      app.show();
   }
   public VirtualProxyTest() {
      super("Virtual Proxy Test");
      // Create an image icon and an image-icon proxy.
      imageIcon = new ImageIcon(IMAGE_NAME);
      imageIconProxy = (Icon)Proxy.newProxyInstance(
                        imageIcon.getClass().getClassLoader(),
                        imageIcon.getClass().getInterfaces(),
                        new ImageIconInvocationHandler(IMAGE_NAME,
                                    IMAGE_WIDTH, IMAGE_HEIGHT));
      // Set the bounds of the frame, and the frame's default
      // close operation.
      setBounds(FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }
   public void paint(Graphics g) {
      super.paint(g);
      Insets insets = getInsets();
      imageIcon.paintIcon(this, g, insets.left, insets.top);
      imageIconProxy.paintIcon(this, g, 
               insets.left + IMAGE_WIDTH + SPACING, // width
               insets.top); // height
   }
}
// ImageIconInvocationHandler is a proxy for an icon.
// The proxy delays loading the image until the first time 
// the image is drawn. While the icon is loading its image, the
// proxy draws a border and the message "Loading image..."  
class ImageIconInvocationHandler implements InvocationHandler {
   private static final String PAINT_ICON_METHOD="paintIcon",
                               GET_WIDTH_METHOD ="getIconWidth",
                               GET_HEIGHT_METHOD="getIconHeight";
   private ImageIcon realIcon = null;
   private boolean isIconCreated = false;
   private String   imageName = null;
   private int width, height;
   public ImageIconInvocationHandler(String imageName,
                                      int width, int height) {
      this.width = width;
      this.height = height;
      this.imageName = imageName;
   }
   public Object invoke(Object proxy, Method m, Object[] args) {
      Object result = null;
      if(PAINT_ICON_METHOD.equals(m.getName())) {
         final Component c = (Component)args[0];
         final Graphics g = (Graphics)args[1];
         final int x = ((Integer)args[2]).intValue(),
                   y = ((Integer)args[3]).intValue();
         if(isIconCreated) {
              realIcon.paintIcon(c, g, x, y);
         }
         else {
              g.drawRect(x, y, width-1, height-1);
            g.drawString("Loading image...", x+20, y+20);
            // The image is loaded via a Runnable passed to
            // SwingUtilties.invokeLater(), which means that
            // it is executed on another thread. 
            SwingUtilities.invokeLater(new Runnable() {
               public void run() {
                  try {
                     // Slow down the image-loading process.
                     Thread.currentThread().sleep(2000);
                     // ImageIcon constructor creates the image.
                     realIcon = new ImageIcon(imageName);
                     isIconCreated = true;
                  }
                  catch(InterruptedException ex) {
                     ex.printStackTrace();
                  }
                  c.repaint();
               }
            });
         }
      }
      else if(GET_WIDTH_METHOD.equals(m.getName())) {
         return isIconCreated ?  new Integer(height) : 
                new Integer(realIcon.getIconHeight()); 
      }
      else if(GET_HEIGHT_METHOD.equals(m.getName())) {
         return isIconCreated ?  new Integer(width) : 
                new Integer(realIcon.getIconWidth())rticle.txt
                ; 
      }
      return null;
   }
}


If you compare Example 6 with Example 3, you may conclude that the JDK's built-in support for the Proxy pattern is not for you, because Example 6 is a bit more complicated than Example 3. In this case, I would prefer Example 3 myself -- the JDK's built-in support for the Proxy pattern is much more useful when a proxy implements many methods that simply delegate to the real subject with only a few methods that embellish the real subject.

  • Print
  • Feedback

Resources