Introduction

Proxies are also called surrogates, handles, and wrappers. They are closely related in structure, but not purpose, to Adapters and Decorators. Proxy Pattern provides a representative for another object in order to control the client’s access to it. There are a number of ways it can manage that access. Common situations in which the Proxy pattern is applicable.

  • A Virtual Proxy controls access to an object that is expensive to instantiate.
  • A Remote Proxy manages interaction between a client and a remote object.
  • A Protection Proxy controls access to the methods of an object based on the caller. It controls access to a sensitive master object.

Intent

  • Provide a surrogate or placeholder for another object to control access to it.
  • Use an extra level of indirection to support distributed, controlled, or intelligent access.
  • Add a wrapper and delegation to protect the real component from undue complexity.

Implementattion

Participants classes in the proxy pattern are:

  • Subject : Interface implemented by the RealSubject and representing its services. The interface must be implemented by the proxy as well so that the proxy can be used in any location where the RealSubject can be used.
  • Proxy : Maintains a reference that allows the Proxy to access the RealSubject. It implements the same interface implemented by the RealSubject so that the Proxy can be substituted for the RealSubject.
  • RealSubject : The real object that the proxy represents.

Example

// Create an interface.
public interface Image {
   void display();
}

// Concrete classes implementing the same interface.
public class RealImage implements Image {

   private String fileName;

   public RealImage(String fileName){
      this.fileName = fileName;
      loadFromDisk(fileName);
   }

   @Override
   public void display() {
      System.out.println("Displaying " + fileName);
   }

   private void loadFromDisk(String fileName){
      System.out.println("Loading " + fileName);
   }
}

public class ProxyImage implements Image{

   private RealImage realImage;
   private String fileName;

   public ProxyImage(String fileName){
      this.fileName = fileName;
   }

   @Override
   public void display() {
      if(realImage == null){
         realImage = new RealImage(fileName);
      }
      realImage.display();
   }
}

// Use the ProxyImage to get object of RealImage class when required.
public class ProxyPatternDemo {
  
   public static void main(String[] args) {
      Image image = new ProxyImage("test.jpg");

      // Image will be loaded from disk
      image.display(); 
      System.out.println("");
      
      // Image will not be loaded from disk
      image.display(); 	
   }
}