The Proxy Pattern is a structural design pattern that provides a surrogate to an actual object. The idea behind the pattern is to allow controlling access to the object. A Proxy does the same work as an object, but explicitly handles the calls to methods in that object.
The Proxy Pattern is used when we want to provide controlled access to an object. It is used to provide a surrogate or placeholder for an object to control access to it. The primary work of a Proxy is to forward method calls to the actual object and potentially do something before or after forwarding the call.
A common use case for Proxy is remote object communication. In this scenario, the Proxy behaves as if it were the actual object. The client that interacts with the Proxy is unaware of any communication happening beyond the Proxy. This scenario is also known as a Remote Proxy.
Another use case is virtual proxy for objects that are expensive to instantiate. When it is costly to create actual objects or load the objects, a Proxy can be a representation of the actual object that loads the actual object when necessary. An example could be loading large images on demand.
A third use case is a protection proxy. In this scenario, the Proxy is used for enforcement of security policies. A protection Proxy ensures that the client follows the security regulations before they can use the actual object. An example could be to restrict the access to sensitive documents in a company by checking the access level of the user before granting access to documents.
A Java code example for the Proxy pattern using Remote Proxy would look like this:
//Interface for remote service
public interface RemoteService {
public void performOperation();
}
//Service implementation class
public class RemoteServiceImpl implements RemoteService {
@Override
public void performOperation() {
System.out.println("Performing operation...");
}
}
//Remote Proxy class
public class RemoteProxy implements RemoteService {
private RemoteService remoteService;
public RemoteProxy() {
remoteService = new RemoteServiceImpl(); // Actual object inside the proxy
}
@Override
public void performOperation() {
//Additional control can be added before and after delegating the request.
remoteService.performOperation();
}
}
//Client code
public class Client {
public static void main(String[] args) {
RemoteService object = new RemoteProxy();
object.performOperation(); //performing operation...
}
}
In this example, the Remote Proxy takes care of delegating to an actual object, ‘RemoteServiceImpl‘ in this case, and provides additional functionality, like extra security checks or remote communication for the client unaware of the communication happening beyond the Proxy.