JB Header
Proxy Design Pattern in Java
This tutorial explains Proxy design pattern in java with class diagrams and example code. Introduction Proxy Design Pattern is a structural design pattern among the Gang Of Four(GOF)Article on GOF Patterns & their types Design Patterns. A structural design pattern deals with how the relationships between objects are realized to make the design better. What is Proxy Design Pattern Proxy pattern specifies a design where substitute or placeholder object is put in-place of the actual target object to control access to it. Client accesses the proxy object to work with the target object. There are many practical usages and applications of using a target object through a proxy. Lets have a look at the major ones. Usages and Applications of Proxy Pattern
  1. Remote Proxy - Using a remote proxy, clients can access objects on a remote location as if they are co-located with them. In Java, using the java.rmi.Remote interface of RMI is an example of this.
  2. Virtual Proxy - A virtual proxy creates an instance of an expensive Object only on demand. I.e. it saves on resources by not creating an instance of an Object heavy on resources until it is needed.
  3. Protection Proxy - A protection proxy regulates access to the original object. Its similar to authroization i.e. object access is controlled based on access rights defined for that Object.
  4. Smart Reference - A smart reference proxy does additional actions when an object is accessed which typically include things like loading a persistent object into memory when its first referenced, locking of objects to avoid inconsistencies in data held by the object etc. It can also keep track of current usage of the real object and in case it is no longer used then a smart reference unloads the object from memory to load it back only when its needed.
Class Diagram for Proxy Design Pattern
Proxy Design Pattern Class Diagram
Explanation of Class Diagram
  • RealSubject is the class which contains the logic to be executed.
  • Proxy object contains the instance of RealSubject and controls access to its someAction() method.
  • Client cannot use a RealSubject instance directly. It must obtain an instance of Proxy first. However, this delegation of responsibility from RealSubject to Proxy is transparent for Client. I.e. client still thinks that its working with RealSubject.
  • To enable this substitution of RealSubject by Proxy one more layer of abstraction exists above Proxy & RealSubject, i.e. the Subject Class.
  • Client contains a reference to this Subject class.
  • Subject reference in Client contains an instance of Proxy class (which is possible as both Proxy and RealSubject are children of Subject)
  • When client invokes someAction() on Subject which actually contains an object of Proxy, then Proxy invokes someAction() method on RealSubject. So, Proxy gets the request from Client, does some work on incoming request, such as authentication/loading of value/remote access initiatation etc and invokes the someAction() method on RealSubject. This extra work which Proxy gets to do on the incoming request is one of the primary advantages of using the Proxy Pattern.
  • Proxy can do the same processing in reverse also when it receives a response from RealSubject object. After processing/massaging the response Proxy returns the final response to Client.
  • In the whole process Client thinks its using the RealSubject directly, however, in reality its the Proxy object which controls access to RealSubject.
Example in Java - Class Diagram
Proxy Design Pattern in Java Class Diagram
Code for the classes shown in Java Class Diagram
//TextFile.java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public abstract class TextFile{
  public abstract String getNameWithPath();
  public abstract FileInputStream getFileContents() throws java.io.FileNotFoundException;
  public static TextFile getTextFileInstance(String fileNameWithPath){
    return new TextFileProxy(fileNameWithPath);
  }
}
//RealTextFile.java
import java.io.FileInputStream;
import java.io.File;
import java.io.FileNotFoundException;
public class RealTextFile extends TextFile{
  private String fileNameWithPath;
  public RealTextFile(String fileNameWithPath){
    this.fileNameWithPath=fileNameWithPath; 
  } 
  public String getNameWithPath(){
    return this.fileNameWithPath;
  }
  public FileInputStream getFileContents() throws FileNotFoundException{
    File file=new File(this.fileNameWithPath);
    return new FileInputStream(file);
  }  
}
//TextFileProxy.java
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class TextFileProxy extends TextFile{
  private String fileNameWithPath;
  RealTextFile realTextFile=null;
  public TextFileProxy(String fileNameWithPath){
    this.fileNameWithPath=fileNameWithPath; 
  } 
  public String getNameWithPath(){
    return this.fileNameWithPath;
  }
  public FileInputStream getFileContents() throws FileNotFoundException{
    this.realTextFile=new RealTextFile(this.fileNameWithPath);
    return realTextFile.getFileContents();
  }  
} 
//Client.java
import java.io.FileNotFoundException;
public class Client{
  public static void main(String args[]){
    TextFile textFile=TextFile.getTextFileInstance("C:\\tests\\test1.txt");
    System.out.println("TextFile's name with path is->"+textFile.getNameWithPath());
    //Till here TextFileProxy instance is created with the realTextFile instance in it being null
   try{
      System.out.println("TextFile's content ->"+textFile.getFileContents());
    }catch(FileNotFoundException fnfe){
      System.out.println("FileNotFoundException exception thrown");
    } 
  //At this point an instance of RealTextFile has been created
  } 
}
 OUTPUT of the above code
TextFile's name with path is->C:\tests\test1.txt
TextFile's content ->java.io.FileInputStream@5de9d0e3
Explanation of Code & Class Diagram The Java class diagram above depicts proxy pattern implemented for a text file reader application where -
  • TextFile is an abstract class which is the base class for all text files.
  • TextFile has 2 abstract methods - getNameWithPath() which returns name of the file with system path to of the file appended, and getFileContents() which returns the contents of the file as a FileInputStream instance.
  • TextFile also has a static method for returning an instance to it called getTextFileInstance(). This is where Proxy part kicks in as this method instead of returning a RealTextFile instance returns a TextFileProxy instance.
  • RealTextFile is a sub-class of TextFile and it contains the actual contents of a file.
  • TextFileProxy is also a sub-class of TextFile. As mentioned earlier, when a new TextFile instance is requested via the getTextFileInstance() then a TextFileProxy instance is returned which just holds the file name & path String value. The actual instance of a file, i.e. a RealTextFile instance, is only created by a TextFileProxy when the Client wants to get the contents of the text file using getFileContents() method. At this point, TextFileProxy creates a new instance of RealTextFile with the fileNameWithPath value stored in it.TextFileProxy then assigns the RealTextFile instance to the class attribute realTextFile and then returns the contents of the text file using realTextFile.getFileContents()
  • If you take a look at the code in main() method in Client class then initially a new TextFile instance is created using the static method getTextFileInstance(). On printing the file name with path it gets printed from TextFileProxy instance.
  • Next when the textFile.getFileContents() is invoked, then internally RealTextFile's instance is invoked as explained above and a FileInputStream object is returned.
  • In the output -
    • First the file's path is printed from TextFileProxy instance when textFile.getNameWithPath() is invoked.
    • Then, the FileInputStream's reference object's information is printed when the textFile.getFileContents() is invoked
    • textFile.getFileContents() actually invokes TextFileProxy’s getFileContents() which in turn instantiates and invokes RealTextFile instance's getFileContents()
Summary In the above tutorial we looked at what is proxy design pattern with its common usages and applications. We then looked at the class diagram for a proxy design pattern & its explanation, followed by a Java example of proxy pattern with its class diagram and explanation. This concludes the tutorial on proxy design pattern.