A Proxy can also be defined as a surrogate. In the real world a credit card is a proxy for what is in our bank account.
It can be used in place of cash and provides a means of accessing that cash when required. This is exactly what the Proxy pattern does, controls and manages access to the object that is being protected. The Proxy pattern is classified as a structural pattern, as it is used to form large object structures across many disparate objects. The definition of the Proxy provided in the original Gang of Four book on Design Patterns states:
Allows for object level access control by acting as a pass through entity or a placeholder object.
To save on the amount of memory used, you might use a Proxy. vSimilarly, if you want to control access to an object, the pattern becomes useful. The diagram below describes the pattern in more detail.
When dealing with design patterns we code to an interface. In this case, the interface that the client knows about is the Subject. Both the Proxy and RealSubject objects implement the Subject interface, but the client may not be able to access the RealSubject without going through the Proxy. It is quite common that the Proxy would handle the creation of the RealSubject object, but it will at least have a reference to it so that it can pass messages along. The diagram below describes this action with a sequence diagram.
Proxy Pattern Purpose
The Proxy is providing a barrier between the client and the real implementation.
There are different variations of the Proxy pattern, depending on it's purpose.
You may have a protection proxy to control access rights to an object.
A virtual proxy handles the case where an object might be expensive to create, and
a remote proxy controls access to a remote object.
You may have noticed that this is very similar to the Adapter pattern.
However, the main difference between the two patterns is that the adapter will expose a different interface to allow interoperability.
The Proxy pattern exposes the same interface, but gets in the way to save processing time or memory.
When should I use this Pattern?
This pattern is recommended when either of the following scenarios occur in your application:
The object being represented is external to the system.
Objects need to be created on demand.
Access control for the original object is required
Added functionality is required when an object is accessed.
Proxy Pattern used in Networks
Usually you will want to use a proxy when communication with a third party is an expensive operation, perhaps over a network.
The proxy would allow you to hold your data until you are ready to commit to the database, and can limit the amount of times that the communication is called. The proxy is also useful if you want to decouple actual implementation code from the access to a particular library. Proxy is also useful for access to large files, or graphics. By using a proxy, you can delay loading the resource until you really need the data inside.
Without the concept of proxies, an application could be slow, and appear non-responsive. First, we should create a common interface for the real and proxy implementations to use:
package com.java.structural.proxy;
public interface Image{
public void displayImage();
}
The RealImage implementation of this interface works as you'd expect:
package com.java.structural.proxy;
public class RealImage implements Image{
public RealImage(URL url){
//load up the image
loadImage(url);
}
public void displayImage(){
//display the image
}
//a method that only the real image has
private void loadImage(URL url){
//do resource intensive operation to load image
}
}
Now the Proxy implementation can be written, which provides access to the RealImage class.
Note that it's only when we call the displayImage() method that it actually uses the RealImage. Until then, we don't need the data.
package com.java.structural.proxy;
public class ProxyImage implements Image{
private URL url;
public ProxyImage(URL url) {
this.url = url;
}
//this method delegates to the real image
public void displayImage(){
RealImage real = new RealImage(url);
real.displayImage();
}
}