Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
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 6
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:
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.