Google

Jun 5, 2014

Difference between proxy and decorator design patterns with a Java example

Are you a Java beginner or a seasoned professional? Java design pattern interview questions are unavoidable. You should do just more than giving factory or singleton design pattern as examples. Good interviewers will be looking for key terms like intent, and practical examples.

In the last post, I looked at the difference between a decorator design pattern and a chain of responsibility design pattern. In this post, let's look at the difference between a decorator and a proxy design design. Often, the proxy, decorator, and the adapter design patterns look similar, but the intent and how you use them are different.

Q. Explain Proxy is compile-time, and decorator and adapter patterns are at run time?
A. A proxy simply delegates all calls to the underlying subject for purposes such as delaying costly operations, hiding the remote object, or providing access control, etc. This basically means that what a proxy can do is decided at compile time and cannot be changed by the calling code after substantiation. Using the decorator pattern the behavior of the underlying object can be changed at run time by adding multiple decorators to it. This addition of behavior takes place at run time.




Q. What is the difference between a decorator and a proxy?
A.

Intent: Decorator is for enhancement (as the name guide), Proxy is for helping with improving performance via lazy loading, controlling access, and hiding remoteness.

Occurrence: Decorator is  run time, and Proxy is compile time, Relationship between a Proxy and the real subject is typically set at compile time, Proxy instantiates it in some way and store the subject in the proxy, whereas Decorator or Adapter are assigned to the subject at run time, knowing only subject's interface.



Step 1: Define the interface

import java.io.File;

public interface FileLoader {
       void loadData(File file);
}

Step 2: Define the subject. which does the actual work of loading the file data.

import java.io.File;

public class FileLoaderImpl implements FileLoader {
 
 @Override
 public void loadData(File file) {
  System.out.println("loading data ...........");
 }
}

Step 3: The proxy that provides access control, lazy loading, and synchronization, and then delegates the invocation to the subject. Proxy knows who the subject is, and cannot be changed once constructed.

import java.io.File;

public class FileLoaderProxy implements FileLoader {

 private User user;
 private volatile FileLoader fileLoader; ////visible to other threads
 private static Object lock = new Object();

 public FileLoaderProxy(User user) {
  this.user = user;
 }

 @Override
 public void loadData(File file) {
  // proxy providing access control
  if (user.okToAccess()) {
   // proxy providing synchronisation
   synchronized (lock) {
    // proxy laziliy load
    if (fileLoader == null) {
     fileLoader = new FileLoaderImpl();
    }
    fileLoader.loadData(file);
   }
  } else {
   throw new RuntimeException("Access denied for user: " + user.getName());
  }
 }
}



Step 4: The caller, client or invoker that communicates to the subject via the proxy.
import java.io.File;

public class FileLoaderTest {
 
 public static void main(String[] args) {
  User user = new User("test", "test");
  FileLoader proxyLoader = new FileLoaderProxy(user);
  proxyLoader.loadData(new File("c:\temp\temp.txt"));  
 }
}


Q. Can you give some practical examples of proxy design pattern?
A.

1. Hibernate uses proxy objects to provide lazy loading.
2. RMI and EJB uses proxy stubs, which know how to communicate remotely with the skeleton.
3. Any other scenarios where proxy

-- hides information about the real object (i.e. subject)
-- provides optimization like lazy loading or synchronization to provide thread-safety
-- provides house keeping tasks like auditing/logging or services like deadlock retry with dynamic proxies.


You may also like:

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home