How to implement Proxy pattern in Java?

Let’s say you want to load a file from a server.

There is an API available which does the actual action of loading the file.

But calling it every time overloads the server.

Instead you can introduce a proxy in between which will fetch the file the first time and then put it on cache. Every subsequent requests will fetch the file from the cache instead of hitting the server.

That explains Proxy pattern.

Proxy acts as an intermediate between a request for an object and the actual object .

Here is the client code for the scenario I explained:

package structural.proxy.pattern;

import java.io.File;

public class Client {
	
	
	public static void main(String a[]) {
		
		FileLoaderProxy proxy = new FileLoaderProxy();
		
		File file = proxy.loadFile("designpatterns.pdf");
		
		System.out.println(file);
		
		File fileNew = proxy.loadFile("designpatterns.pdf");
		System.out.println(fileNew);
		
	}

}

The same file is loaded twice using a proxy .

Here is the proxy class:

package structural.proxy.pattern;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

public class FileLoaderProxy implements FileLoader {

	Map<String, File> fileCache = new HashMap<String, File>();

	@Override
	public File loadFile(String fileName) {
		

		if (fileCache.containsKey(fileName)) {

			File fileFromCache = fileCache.get(fileName);
			System.out.println("Loading file from cache");

			return fileFromCache;
		} else {

			FileLoaderReal fileLoader = new FileLoaderReal();
			File newFile = fileLoader.loadFile(fileName);

			fileCache.put(fileName, newFile);

			return newFile;

		}
	}

}

As you can see the file is first searched for in the cache. If it is present it is returned else it calls the real file loader which fetches the file from the server. Once it fetches the file , it puts it on the cache. The next subsequent requests are then served by the cache.

Here is the real file loader class:

package structural.proxy.pattern;

import java.io.File;

public class FileLoaderReal implements FileLoader {

	@Override
	public File loadFile(String fileName) {
		
		System.out.println("Loading file from actual path for the file: ");
		
		return new File(fileName);
	}

}

Both the FileLoaderReal and FileLoaderProxy imlement the same interface . This allows us to place the proxy in place of the real loader file with ease.

Here is the FileLoader interface:

package structural.proxy.pattern;

import java.io.File;

public interface FileLoader {
	
	
	File loadFile(String fileName);

}

Below is the output on running the code :

Loading file from actual path for the file: 
designpatterns.pdf
Loading file from cache
designpatterns.pdf

As you can see , the second fetch is done from the cache.

This is a very simplistic explanation of the proxy pattern that serves well to explain it.

Quoting the Gang of Four :

Place a surrogate or placeholder for another object to control access to it.

They further explain four different types of proxies:

  1. A remote proxy which hides the client from making remote calls and provides an abstraction for it.
  2. A protection proxy which acts as a guard to an object. It validates requests before providing access to an object or method.
  3. A virtual proxy which creates expensive objects on demand. Our example uses a virtual proxy. An object is loaded on demand (we load the file from server only the first time it is requested , further requests are served by the cache)
  4. A smart reference. This proxy does additional actions when an object is accessed. One example is checking if an object is locked before it is accessed .

The code is available here :

https://github.com/vijaysrj/designPatternsGoF/tree/master/src/structural/proxy/pattern


Posted

in

,

by

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading