tl  tr
  Home | Tutorials | Articles | Videos | Products | Tools | Search
Interviews | Open Source | Tag Cloud | Follow Us | Bookmark | Contact   
 Design Patterns > Java Design Patterns > Proxy

Proxy 

Proxy pattern comes under Structural design pattern. It provides the ability to control the access to an object.

Behaviour & Advantages

  • Provide a place holder for another object to control access to it.
  • Can impose security restriction using Proxy.
  • It acts as wrapper and delegates the calls to actual object only when all restrictions imposed by Proxy are satisfied.
Participants
  • Subject
    An abstract interface for Real Subject and Proxy. As both classes implementing the same interface we can use Proxy in place of Real Subject.
  • Real Subject
    Real or actual implementation of Subject interface.
  • Proxy
    A Proxy implementation of Subject interface which delegates to Real Subject. Proxy holds a reference to Real Subject and controls the access to it.
Proxies are categorized into 4 types,
  1. Virtual Proxy is a place holder for a heavy weight object. Actual object creation is delayed until it is really required. Swing Image Proxy is best example for this type.
  2. Remote Proxy is a stub which communicates with a real object deployed on a remote machine. Java RMI and Web Service client Proxies are examples for this type.
  3. Protection Proxy checks that the caller has the access permissions required to perform a request. Time bound and License bound proxies are examples of this type.
  4. Smart Proxy provides a sophisticated access to certain objects such as tracking the number of references to an object and loading an object from database into memory on demand. Hibernate's dynamic proxies are examples of this type.

This examples shows implementing Protection Proxies. Time bound Proxy allows the user to access real object in a specified time frame. Licence bound Proxy allows user to access real object only for specified number of times.

Here IMathService interface acts as Subject and MathService class acts as Real Subject. Class MathServiceExpiryProxy is the Time bound Proxy and MathServiceLicenseProxy is Licence bound Proxy.

File Name  :  
com/bethecoder/tutorials/dp/proxy/IMathService.java 
   
package com.bethecoder.tutorials.dp.proxy;

public interface IMathService {

  /**
   * returns sum of two integers.
   */
  public int add(int a, int b);
}
   

Math Service Real Subject.

File Name  :  
com/bethecoder/tutorials/dp/proxy/MathService.java 
   
package com.bethecoder.tutorials.dp.proxy;

public class MathService implements IMathService {

  @Override
  public int add(int a, int b) {
    return a + b;
  }

}
   

MathServiceExpiryProxy Time bound Proxy.

File Name  :  
com/bethecoder/tutorials/dp/proxy/MathServiceExpiryProxy.java 
   
package com.bethecoder.tutorials.dp.proxy;

public class MathServiceExpiryProxy implements IMathService {

  private long serviceCreationTS = System.currentTimeMillis();
  private long expriesIn = 0;
  private IMathService mathService;

  public MathServiceExpiryProxy(IMathService mathService, long expriesIn) {
    super();
    this.mathService = mathService;
    this.expriesIn = expriesIn;
  }

  @Override
  public int add(int a, int b) {
    long elapsedTime = System.currentTimeMillis() - serviceCreationTS;

    if (elapsedTime < expriesIn) {
      return mathService.add(a, b);
    }
    
    throw new RuntimeException("Service time (" + expriesIn + "ms) expired");
  }

  public IMathService getMathService() {
    return mathService;
  }

  public void setMathService(IMathService mathService) {
    this.mathService = mathService;
  }

}
   

MathServiceLicenseProxy Licence bound Proxy.

File Name  :  
com/bethecoder/tutorials/dp/proxy/MathServiceLicenseProxy.java 
   
package com.bethecoder.tutorials.dp.proxy;

public class MathServiceLicenseProxy implements IMathService {

  private int maxUsage = 0;
  private int currentUsage = 0;
  private IMathService mathService;

  public MathServiceLicenseProxy(IMathService mathService, int maxUsage) {
    super();
    this.mathService = mathService;
    this.maxUsage = maxUsage;
  }

  @Override
  public int add(int a, int b) {

    if (currentUsage < maxUsage) {
      currentUsage ++;
      return mathService.add(a, b);
    }
    
    throw new RuntimeException("Service license (" + maxUsage + " times max usage) expired");
  }

  public IMathService getMathService() {
    return mathService;
  }

  public void setMathService(IMathService mathService) {
    this.mathService = mathService;
  }

}
   

Service Locator class which gets required proxy is shown below,

File Name  :  
com/bethecoder/tutorials/dp/proxy/MathServiceLocator.java 
   
package com.bethecoder.tutorials.dp.proxy;

public class MathServiceLocator {

  /**
   * Service expires in 10 seconds.
   */
  private static long SERVICE_EXPIRY_TIME = 10 1000;
  
  /**
   * Service expires after 4 uses.
   */
  private static int LICENCE_MAX_USAGE = 4;
  
  private MathServiceLocator() {
  }

  public static IMathService getMathExpiryService() {
    return new MathServiceExpiryProxy(new MathService(), SERVICE_EXPIRY_TIME);
  }
  
  public static IMathService getMathLincenseService() {
    return new MathServiceLicenseProxy(new MathService(), LICENCE_MAX_USAGE);
  }
}
   

Time bound Proxy usage is shown below,

File Name  :  
com/bethecoder/tutorials/dp/proxy/Test.java 
   
package com.bethecoder.tutorials.dp.proxy;

public class Test {

  /**
   @param args
   */
  public static void main(String[] args) {

    IMathService mathService = MathServiceLocator.getMathExpiryService();
    int a, b;
    
    for (int i = ; i < 20 ; i ++) {
      a = b = i;
      System.out.println("Sum of a(" + a + ")+b(" + b +")=" + mathService.add(a, b));
      try {
        Thread.sleep(1000);
      catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

}
   

It gives the following output,
Sum of a(0)+b(0)=0
Sum of a(1)+b(1)=2
Sum of a(2)+b(2)=4
Sum of a(3)+b(3)=6
Sum of a(4)+b(4)=8
Sum of a(5)+b(5)=10
Sum of a(6)+b(6)=12
Sum of a(7)+b(7)=14
Sum of a(8)+b(8)=16
Sum of a(9)+b(9)=18
Exception in thread "main" java.lang.RuntimeException: 
		Service time (10000ms) expired
	at com.bethecoder.tutorials.dp.proxy.
		MathServiceExpiryProxy.add(MathServiceExpiryProxy.java:23)
	at com.bethecoder.tutorials.dp.proxy.Test.main(Test.java:15)

License bound Proxy usage is shown below,

File Name  :  
com/bethecoder/tutorials/dp/proxy/Test2.java 
Author  :  Sudhakar KV
Email  :  [email protected]
   
package com.bethecoder.tutorials.dp.proxy;

public class Test2 {

  /**
   @param args
   */
  public static void main(String[] args) {

    IMathService mathService = MathServiceLocator.getMathLincenseService();
    
    int a, b;
    for (int i = ; i < 20 ; i ++) {
      a = b = i;
      System.out.println("Sum of a(" + a + ")+b(" + b +")=" + mathService.add(a, b));
    }
  }

}
   

It gives the following output,
Sum of a(0)+b(0)=0
Sum of a(1)+b(1)=2
Sum of a(2)+b(2)=4
Sum of a(3)+b(3)=6
Exception in thread "main" java.lang.RuntimeException: 
		Service license (4 times max usage) expired
	at com.bethecoder.tutorials.dp.proxy.
		MathServiceLicenseProxy.add(MathServiceLicenseProxy.java:23)
	at com.bethecoder.tutorials.dp.proxy.Test2.main(Test2.java:15)



 
  


  
bl  br