Thursday, July 7, 2022

Structural Design Patterns # Proxy

Proxy is a structural design pattern that lets you provide a substitute or placeholder for another object. A proxy controls access to the original object, allowing you to perform something either before or after the request gets through to the original object

Problem

Why would you want to control access to an object? Here is an example: you have a massive object that consumes a vast amount of system resources. You need it from time to time, but not always.


You could implement lazy initialization: create this object only when it’s actually needed. All of the object’s clients would need to execute some deferred initialization code. Unfortunately, this would probably cause a lot of code duplication.

In an ideal world, we’d want to put this code directly into our object’s class, but that isn’t always possible. For instance, the class may be part of a closed 3rd-party library.

Solution

The Proxy pattern suggests that you create a new proxy class with the same interface as an original service object. Then you update your app so that it passes the proxy object to all of the original object’s clients. Upon receiving a request from a client, the proxy creates a real service object and delegates all the work to it.


But what’s the benefit? If you need to execute something either before or after the primary logic of the class, the proxy lets you do this without changing that class. Since the proxy implements the same interface as the original class, it can be passed to any client that expects a real service object.

Pros and Cons


Proxy Design Pattern  Example

Since we code Java in terms of interfaces, here is our interface and its implementation class..
public interface CommandExecutor {

public void runCommand(String cmd) throws Exception;
}

import java.io.IOException; public class CommandExecutorImpl implements CommandExecutor { @Override public void runCommand(String cmd) throws IOException { //some heavy implementation Runtime.getRuntime().exec(cmd); System.out.println("'" + cmd + "' command executed."); } }

Proxy Design Pattern – Proxy Class

Now we want to provide only admin users to have full access of above class, if the user is not admin then only limited commands will be allowed. Here is our very simple proxy class implementation..

public class CommandExecutorProxy implements CommandExecutor { private boolean isAdmin; private CommandExecutor executor; public CommandExecutorProxy(String user, String pwd){ if("Pankaj".equals(user) && "J@urnalD$v".equals(pwd)) isAdmin=true; executor = new CommandExecutorImpl(); } @Override public void runCommand(String cmd) throws Exception { if(isAdmin){ executor.runCommand(cmd); }else{ if(cmd.trim().startsWith("rm")){ throw new Exception("rm command is not allowed for non-admin users."); }else{ executor.runCommand(cmd); } } } }

Proxy Design Pattern Client Program.

public class ProxyPatternTest { public static void main(String[] args){ CommandExecutor executor = new CommandExecutorProxy("Pankaj", "wrong_pwd"); try { executor.runCommand("ls -ltr"); executor.runCommand(" rm -rf abc.pdf"); } catch (Exception e) { System.out.println("Exception Message::"+e.getMessage()); } } }

Output of above proxy design pattern example program is:
'ls -ltr' command executed. Exception Message::rm command is not allowed for non-admin users.


You may also like

Kubernetes Microservices
Python AI/ML
Spring Framework Spring Boot
Core Java Java Coding Question
Maven AWS