← Back to Advanced Java Course | Chapter 6: Design Patterns | Lesson 12 of 14

Java Proxy Pattern

The Proxy pattern provides a stand-in object implementing the same interface as a real object, controlling access to it and adding behavior like lazy loading, access control, or logging.

What is the Proxy Pattern?

The Proxy pattern provides a stand-in or placeholder object that implements the same interface as a real object, controlling access to it, and adding behavior like lazy loading, access control, or logging around the delegated call.

Example: What is the Proxy Pattern?

java
public class Main {
	interface Image { void display(); }
	static class RealImage implements Image {
		public void display() { System.out.println("Displaying real image"); }
	}
	static class ProxyImage implements Image {
		RealImage real = new RealImage();
		public void display() {
			System.out.println("Logging access"); // adds behavior around the delegated call
			real.display();
		}
	}
	public static void main(String[] args) {
		Image img = new ProxyImage();
		img.display();
	}
}

Virtual Proxy (Lazy Loading)

A virtual proxy delays the creation of an expensive object until it's actually needed, only constructing the real object the first time one of its methods is genuinely called, saving resources when it's never used at all.

Example: Virtual Proxy (Lazy Loading)

java
public class Main {
	interface Image { void display(); }
	static class RealImage implements Image {
		RealImage() { System.out.println("Expensive load happening now"); }
		public void display() { System.out.println("Displaying"); }
	}
	static class VirtualProxy implements Image {
		RealImage real;
		public void display() {
			if (real == null) real = new RealImage(); // constructed only when first needed
			real.display();
		}
	}
	public static void main(String[] args) {
		Image img = new VirtualProxy();
		System.out.println("Proxy created, real image not loaded yet");
		img.display();
	}
}

Protection Proxy (Access Control)

A protection proxy checks whether the caller is authorized before allowing a request to reach the real object, acting as a security gatekeeper that can deny access entirely without the real object ever being involved.

Example: Protection Proxy (Access Control)

java
public class Main {
	interface Document { void open(); }
	static class RealDocument implements Document {
		public void open() { System.out.println("Document opened"); }
	}
	static class ProtectionProxy implements Document {
		RealDocument real = new RealDocument();
		boolean isAdmin;
		ProtectionProxy(boolean isAdmin) { this.isAdmin = isAdmin; }
		public void open() {
			if (isAdmin) real.open(); else System.out.println("Access denied"); // gatekeeper
		}
	}
	public static void main(String[] args) {
		new ProtectionProxy(false).open();
	}
}

Remote Proxy

A remote proxy represents an object that lives on a different machine or process, hiding the details of network communication and serialization behind what looks to the caller like an ordinary local method call.

Example: Remote Proxy

java
public class Main {
	interface Service { String call(); }
	static class RemoteProxy implements Service {
		public String call() {
			return "Simulated network response"; // hides network details behind a local-looking call
		}
	}
	public static void main(String[] args) {
		Service service = new RemoteProxy();
		System.out.println(service.call());
	}
}

Java's Dynamic Proxy

Java provides built-in support for dynamic proxies through java.lang.reflect.Proxy, which generates a proxy class for any interface at runtime and routes every method call through a single InvocationHandler, without writing a dedicated proxy class by hand.

Example: Java's Dynamic Proxy

java
import java.lang.reflect.*;
public class Main {
	interface Greeter { String greet(); }
	public static void main(String[] args) {
		Greeter proxy = (Greeter) Proxy.newProxyInstance(
			Main.class.getClassLoader(),
			new Class[]{Greeter.class},
			(p, method, args2) -> "Hello from dynamic proxy" // one InvocationHandler routes every call
		);
		System.out.println(proxy.greet());
	}
}

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.