A Proxy provides a placeholder for another object to control access to it. Unlike a Decorator, which adds behavior, a Proxy manages the lifecycle or authorization of the underlying subject.
Combining protection and lazy initialization in a single surrogate.
public class SecureImageProxy implements Image {
private RealImage realImage;
private final String filename;
private final User currentUser;
public SecureImageProxy(String filename, User user) {
this.filename = filename;
this.currentUser = user;
}
@Override
public void display() {
// 1. Protection Check
if (!currentUser.hasPermission("VIEW_IMAGES")) {
throw new SecurityException("Access Denied");
}
// 2. Virtual Proxy (Lazy Load)
if (realImage == null) {
realImage = new RealImage(filename); // Expensive I/O happens here
}
realImage.display();
}
}
For cross-cutting concerns that apply to many services (e.g., logging every method call), use java.lang.reflect.Proxy. This allows you to create a proxy at runtime for any interface.
Service original = new RealService();
Service proxy = (Service) Proxy.newProxyInstance(
Service.class.getClassLoader(),
new Class<?>[]{Service.class},
(p, method, args) -> {
long start = System.nanoTime();
Object result = method.invoke(original, args);
System.out.println(method.getName() + " took " + (System.nanoTime() - start) + "ns");
return result;
}
);
RealSubject is synchronized to avoid duplicate creation of expensive resources.See Also: