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 3 of 6

The JDK's built-in support for the Proxy design pattern

The Proxy pattern is one of the most important design patterns because it provides an alternative to extending functionality with inheritance. That alternative is object composition, where an object (proxy) forwards method calls to an enclosed object (real subject).

Object composition is preferable to inheritance because, with composition, enclosing objects can only manipulate their enclosed object through the enclosed object's interface, which results in loose coupling between objects. In contrast, with inheritance, classes are tightly coupled to their base class because the internals of a base class are visible to its extensions. Because of that visibility, inheritance is often referred to as white-box reuse. On the other hand, with composition, the internals of the enclosing object are not visible to the enclosed object (and vice-versa); therefore, composition is often referred to as black-box reuse. All things being equal, black-box reuse (composition) is preferable to white-box reuse (inheritance) because loose coupling results in more malleable and flexible systems.

Because the Proxy pattern is so important, J2SE 1.3 (Java 2 Platform, Standard Edition) and beyond directly supports it. That support involves three classes from the java.lang.reflect package: Proxy, Method, and InvocationHandler. Example 5 shows a simple example that utilizes the JDK support for the Proxy pattern:

Example 5. JDK proxies

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface AnInterface {
   public void doSomething();
}
class AClass implements AnInterface {
   public void doSomething() {
      System.out.println("Inside Method AClass.doSomething()");
   }
}
public class Test {
   public static void main(String args[]) {
      AnInterface realSubject = new AClass();
      AnInterface proxy = (AnInterface)Proxy.newProxyInstance(
                        realSubject.getClass().getClassLoader(),
                        realSubject.getClass().getInterfaces(),
                        new SimpleInvocationHandler(realSubject));
      passMeAProxy(proxy);
   }
   private static void passMeAProxy(AnInterface anInterface) {
      anInterface.doSomething();
   }
}
class SimpleInvocationHandler implements InvocationHandler {
   public SimpleInvocationHandler(Object realSubject) {
      this.realSubject = realSubject;
   }
   public Object invoke(Object proxy, Method m, Object[] args){
      Object result = null;
      System.out.println("Before Calling " + m.getName());
      try {
         result = m.invoke(realSubject, args);   
      }
      catch(Exception ex) {
         System.exit(1);
      }
      System.out.println("After Calling " + m.getName());
      return result;
   }
   private Object realSubject = null;
}


In the preceding example, the static Proxy.newProxyInstance() method creates a proxy for a real subject. Real subjects must implement one or more interfaces, and a reference to a proxy can be passed to any method that expects a reference to one of those interfaces. The main() method passes the proxy to a method that takes a reference to AnInterface, just to prove it can be done. In the preceding example, our simple proxy implements only one interface.

  • Print
  • Feedback

Resources