The Proxy Pattern provides a surrogate or placeholder for another object to control access to it.
The Proxy Pattern provides a representative for another object in order to control the client’s access to it.
There are a number of ways it can manage that access.
Remote Proxy: manages interaction between a client and a remote object.
Virtual Proxy: controls access to an object that is expensive to instantiate.
Protection Proxy: controls access to the methods of an object based on the caller.
Other variants of the Proxy Pattern are the following:
Firewall Proxy: controls access to a set of network resources, protecting the subject from malicious clients. This is used in corporate firewall systems.
Smart Reference Proxy: provides additional actions whenever a subject is referenced, such as counting the number of references to an object. In C++ this is a shared smart pointer.
Caching Proxy: provides t3emporary storage for results of operations that are expensive. It can also allow multiple clients to share the results to reduce computation or network latency. This is often seen in web server proxies as well as content management and publishing systems.
Synchronization Proxy: provides safe access to a subject from multiple threas. This proxy is used in JavaSpaces, where it controls synchronized access to an underlying set of objects in a distributed environment.
Complexity Hiding Proxy: hides the complexity of and controls access to a complex set of classes. This is sometimes called the Facade Proxy. The Complexity Hiding Proxy differs from the Facade Pattern in that the proxy controls access, while the Facade Pattern just provides an alternative interface.
Copy-On-Write Proxy: controls the opying of an object by deferring the copying of an object until it is required by a client. This is a variant of the Virtual Proxy.
Remote Proxy Pattern Example
The following example shows a company that has GumballMachines which they want to monitor remotely.
To do this, we use a GumballMonitor that will talk to a proxy, which knows how to talk to the remote GumballMachines and how to return a report from the state of the GumballMachine.
The first step is to turn the GumballMachine into a service that can handle remote requests from clients.
To do that, we need to:
Create a remote interface for the GumballMachine. This will provide a set of methods that can be called remotely.
Make sure all the return types in the interface are serializable.
Implement the interface in a concrete class.
Let’s start with the remote interface:
The State class is not yet serializable. To fix this we use the following implementation:
Each State has a reference to a GumballMachine which should not be serialized.
In Java this can be achieved with the transient keyword as shown with the
following NoQuarterState class.
The GumballMachine class needs to act as a service and handle request coming over the network.
Therefore the GumballMachine needs to implement the GumballMachineRemote interface.
To let the GumballMachine serve requests, we need to make sure we register it with the
RMI registry, which is Java’s Remote Method Invocation registry. This allows clients to locate this service. The following test code takes care of the registration:
The constructor of the GumballMachine can throw exceptions because it extends the Java UnicastRemoteObject class.
Therefore the creation of GumballMachine needs to be placed inside a try and catch statement.
The call to Naming.rebind publishes the GumballMachine stub under the name gumballmachine.
For the GumballMonitor to work over the network, we have to rely on the remote interface GumballMachineRemote.
This class will also catch any exceptions that might happen when requests over the network happen.
To monitor a bunch of remote GumballMachines we can use the following test program:
It uses the locations to monitor to create an array of GumballMonitors.
Then it uses a GumballMachineRemote proxy to iterate through the state of each GumballMachine.
Here is the output after running the two test programs: