November 27, 2020
Hot Topics:

Design Pattern: Proxy

  • By Jeff Langr
  • Send Email »
  • More Articles »

A proxy is a stand-in for something or someone else. As an actor, you might hire a proxy to attend an autograph signing session. Your proxy is providing a layer between you and your fans, but can forward relevant messages as necessary. You want your proxy to behave as much like you do as possible, so that the fans believe they are interacting with you directly.

Proxies in software are similar to proxies in real life. You might create a distributed object proxy. Such a proxy is designed to make its clients think that they are directly interacting with the object, when in reality the object lives in a process on a remote machine. The proxy manages the intricacies of communicating with the distributed object while ensuring that the client remains blissfully ignorant of these details.

As you might imagine, proxies in Java are heavily dependent upon having both the proxy and the target class—the class that the proxy is "standing in" for—implement a common interface. The proxy needs to respond to all the same messages as the target, and forward them as appropriate.

In this article, I'll demonstrate use of a proxy that provides a security layer, disallowing clients with insufficient access from executing specific methods.

I've built a Portfolio class using test-driven development (TDD). The simple implementation of Portfolio provides two query methods, numberOfHoldings and sharesOf, and one update method named purchase.

Listing 1: PortfolioTest

import static org.junit.Assert.*;
import org.junit.*;

public class PortfolioTest {
   private Portfolio portfolio;

   public void initialize() {
      portfolio = new Portfolio();

   public void containsNoHoldingsOnCreation() {
      assertEquals(0, portfolio.numberOfHoldings());

   public void storesSinglePurchaseSingleShare() {
      assertEquals(0, portfolio.sharesOf("MSFT"));
      portfolio.purchase("MSFT", 1);
      assertEquals(1, portfolio.numberOfHoldings());
      assertEquals(1, portfolio.sharesOf("MSFT"));

   public void sumsSharesForMultiplePurchasesSameSymbol() {
      portfolio.purchase("MSFT", 1);
      portfolio.purchase("MSFT", 2);
      assertEquals(1, portfolio.numberOfHoldings());
      assertEquals(3, portfolio.sharesOf("MSFT"));

   public void segregatesSharesBySymbol() {
      portfolio.purchase("MSFT", 5);
      portfolio.purchase("IBM", 10);
      assertEquals(2, portfolio.numberOfHoldings());
      assertEquals(5, portfolio.sharesOf("MSFT"));

   public void disallowsPurchaseOfNullSymbol() {
      portfolio.purchase(null, 0);

Listing 2: Portfolio

import java.util.*;

public class Portfolio {
   private Map<String,Integer> symbols =
      new HashMap<String,Integer>();

   public int numberOfHoldings() {
      return symbols.size();

   public int sharesOf(String symbol) {
      if (!symbols.containsKey(symbol))
         return 0;
      return symbols.get(symbol);

   public void purchase(String symbol, int shares) {
      if (symbol == null)
         throw new InvalidSymbolException();
      symbols.put(symbol, shares + sharesOf(symbol));

The InvalidSymbolException class is simply an empty subclass of RuntimeException.

The first step toward building a proxy is to define a common interface. I execute an Extract Implementer refactoring [Feathers2004], ending up with an interface named Portfolio and an implementation of the Portfolio interface named PortfolioImpl.

Listing 3: Introducing an interface

// Portfolio.java
public interface Portfolio {
   int numberOfHoldings();
   int sharesOf(String symbol);
   void purchase(String symbol, int shares);

// PortfolioImpl.java--renamed from Portfolio
import java.util.*;

public class PortfolioImpl implements Portfolio {

Page 1 of 4

This article was originally published on August 1, 2007

Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date