Java Omnibus
OOAD & Architecture / GoF patterns / Structural / Proxy Pattern in Java
GoF Structural Java Order Management
GoF Pattern

Proxy is the right wrapper when you need to control access to an object rather than change its interface or simplify a subsystem.

Provide a surrogate or placeholder for another object in order to control access to it.

Intent

What the pattern is trying to do

Provide a surrogate or placeholder for another object in order to control access to it.

Problem

What force creates the need

A client should see the same interface, but calls need mediation for access control, lazy loading, remote invocation, or caching.

Solution

How the pattern responds

Insert a proxy that implements the same interface and adds access logic around delegation to the real subject.

Structure

How the moving parts fit together

Client and real subject share an interface, while the proxy stands in front and controls when or how the real object is reached.

Java Example

Java example in the Order Management domain

Proxy Pattern in Java example
package org.javaomnibus.ecommerce.gof.structural;

public interface CustomerProfileRepository {
    CustomerProfile findById(String customerId);
}

public final class SecureCustomerProfileRepositoryProxy implements CustomerProfileRepository {
    private final CustomerProfileRepository target;
    private final AccessPolicy accessPolicy;

    public SecureCustomerProfileRepositoryProxy(
        CustomerProfileRepository target,
        AccessPolicy accessPolicy
    ) {
        this.target = target;
        this.accessPolicy = accessPolicy;
    }

    @Override
    public CustomerProfile findById(String customerId) {
        accessPolicy.requirePermission("customer-profile:read");
        return target.findById(customerId);
    }
}
Code Walkthrough

Step by step

  1. The client still depends on CustomerProfileRepository.
  2. The proxy adds access checks before delegation.
  3. The interface stays the same, which distinguishes Proxy from Adapter.
  4. Proxy is especially clear when the force is access, remoting, lazy loading, or caching.
When To Use

Where this pattern helps

  • When access control, caching, remote access, or lazy loading should be added transparently
  • When clients should keep the same interface while object access is mediated
When Not To Use

When a simpler design is better

  • When the problem is subsystem simplification or interface mismatch instead
  • When a direct collaborator with explicit logic would be clearer than a transparent stand-in
Trade-Offs

What this pattern costs

  • Transparent mediation can hide important performance or remoting costs
  • Too many proxies can make behavior and debugging paths harder to reason about
Modern Relevance

How this fits today

Proxy remains common in Java through security wrappers, remote stubs, virtual proxies, ORM lazy loading, and framework-generated dynamic proxies.

Common Misuse

Where teams get it wrong

Calling any wrapper a proxy blurs an important distinction; if the wrapper changes the interface or simplifies a subsystem, it is solving a different problem.

Related Patterns

Compare with nearby choices


What To Read Next