Proxy pattern


In computer programming, the proxy pattern is a software design pattern. A proxy, in its most general form, is a class functioning as an interface to something else. The proxy could interface to anything: a network connection, a large object in memory, a file, or some other resource that is expensive or impossible to duplicate. In short, a proxy is a wrapper or agent object that is being called by the client to access the real serving object behind the scenes. Use of the proxy can simply be forwarding to the real object, or can provide additional logic. In the proxy, extra functionality can be provided, for example caching when operations on the real object are resource intensive, or checking preconditions before operations on the real object are invoked. For the client, usage of a proxy object is similar to using the real object, because both implement the same interface.

Overview

The Proxy
design pattern is one of the twenty-three well-known
GoF design patterns
that describe how to solve recurring design problems to design flexible and reusable object-oriented software, that is, objects that are easier to implement, change, test, and reuse.

What problems can the Proxy design pattern solve?

When accessing sensitive objects, for example, it should be possible to check that clients have the needed access rights.

What solution does the Proxy design pattern describe?

Define a separate Proxy object that
This enables to work through a Proxy object to perform additional functionality when accessing a subject. For example, to check the access rights of clients accessing a sensitive object.
To act as substitute for a subject, a proxy must implement the Subject interface.
Clients can't tell whether they work with a subject or its proxy.
See also the UML class and sequence diagram below.

Structure

UML class and sequence diagram

In the above UML class diagram,
the Proxy class implements the Subject interface so that it can act as substitute for Subject objects. It maintains a reference
to the substituted object so that it can forward requests to it
.
The sequence diagram
shows the run-time interactions: The Client object
works through a Proxy object that
controls the access to a RealSubject object.
In this example, the Proxy forwards the request to the RealSubject, which performs the request.

Class diagram

Possible usage scenarios

Remote proxy

In distributed object communication, a local object represents a remote object. The local object is a proxy for the remote object, and method invocation on the local object results in remote method invocation on the remote object. An example would be an ATM implementation, where the ATM might hold proxy objects for bank information that exists in the remote server.

Virtual proxy

In place of a complex or heavy object, a skeleton representation may be advantageous in some cases. When an underlying image is huge in size, it may be represented using a virtual proxy object, loading the real object on demand.

Protection proxy

A protection proxy might be used to control access to a resource based on access rights.

Example

PHP


interface Image
// On System A
class RealImage implements Image
// On System B
class ProxyImage implements Image
$image1 = new ProxyImage;
$image2 = new ProxyImage;
$image1->displayImage; // Loading necessary
$image1->displayImage; // Loading unnecessary
$image2->displayImage; // Loading necessary
$image2->displayImage; // Loading unnecessary
$image1->displayImage; // Loading unnecessary

The program's output is:
Loading HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Loading HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo1

C#


interface ICar
// Real Object
public class Car : ICar
// Proxy Object
public class ProxyCar : ICar
public class Driver
// How to use above Proxy class?
private void btnProxy_Click

Output
Sorry, the driver is too young to drive.
Car has been driven!
Notes:

  1. include
  2. include
class ICar ;
class Car : public ICar ;
class ProxyCar : public ICar ;
int main

Crystal


abstract class AbstractCar
abstract def drive
end
class Car < AbstractCar
def drive
puts "Car has been driven!"
end
end
class Driver
getter age : Int32
def initialize
end
end
class ProxyCar < AbstractCar
private getter driver : Driver
private getter real_car : AbstractCar
def initialize
@real_car = Car.new
end
def drive
if driver.age <= 16
puts "Sorry, the driver is too young to drive."
else
@real_car.drive
end
end
end
  1. Program
driver = Driver.new
car = ProxyCar.new
car.drive
driver = Driver.new
car = ProxyCar.new
car.drive

Output
Sorry, the driver is too young to drive.
Car has been driven!

Delphi / Object Pascal


// Proxy Design pattern
unit DesignPattern.Proxy;
interface
type
// Car Interface
ICar = interface
procedure DriveCar;
end;
// TCar class, implementing ICar
TCar = Class
class function New: ICar;
procedure DriveCar;
End;
// Driver Interface
IDriver = interface
function Age: Integer;
end;
// TDriver Class, implementing IDriver
TDriver = Class
private
FAge: Integer;
public
constructor Create; Overload;
class function New: IDriver;
function Age: Integer;
End;
// Proxy Object
TProxyCar = Class
private
FDriver: IDriver;
FRealCar: ICar;
public
constructor Create; Overload;
class function New: ICar;
procedure DriveCar;
End;
implementation
class function TCar.New: ICar;
begin
Result := Create;
end;
procedure TCar.DriveCar;
begin
WriteLn;
end;
constructor TDriver.Create;
begin
inherited Create;
FAge := Age;
end;
class function TDriver.New: IDriver;
begin
Result := Create;
end;
function TDriver.Age: Integer;
begin
Result := FAge;
end;
constructor TProxyCar.Create;
begin
inherited Create;
Self.FDriver := Driver;
Self.FRealCar := TCar.Create AS ICar;
end;
class function TProxyCar.New: ICar;
begin
Result := Create;
end;
procedure TProxyCar.DriveCar;
begin
if
then WriteLn
else FRealCar.DriveCar;
end;
end.

Usage

program Project1;
uses
DesignPattern.Proxy in 'DesignPattern.Proxy.pas';
begin
TProxyCar.New.DriveCar;
TProxyCar.New.DriveCar;
end.

Output
Sorry, the driver is too young to drive.
Car has been driven!

Java

The following Java example illustrates the "virtual proxy" pattern. The ProxyImage class is used to access a remote method.
The example creates first an interface against which the pattern creates the classes. This interface contains only one method to display the image, called displayImage, that has to be coded by all classes implementing it.
The proxy class ProxyImage is running on another system than the real image class itself and can represent the real image RealImage over there. The image information is accessed from the disk. Using the proxy pattern, the code of the ProxyImage avoids multiple loading of the image, accessing it from the other system in a memory-saving manner. The lazy loading demonstrated in this example is not part of the proxy pattern, but is merely an advantage made possible by the use of the proxy.

interface Image
// On System A
class RealImage implements Image
// On System B
class ProxyImage implements Image
class ProxyExample

The program's output is:
Loading HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Displaying HiRes_10MB_Photo1
Loading HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo2
Displaying HiRes_10MB_Photo1

Python


"""
Proxy pattern example.
"""
from abc import ABCMeta, abstractmethod
NOT_IMPLEMENTED = "You should implement this."
class AbstractCar:
__metaclass__ = ABCMeta
@abstractmethod
def drive:
raise NotImplementedError
class Car:
def drive -> None:
print
class Driver:
def __init__ -> None:
self.age = age
class ProxyCar:
def __init__ -> None:
self.car = Car
self.driver = driver
def drive -> None:
if self.driver.age <= 16:
print
else:
self.car.drive
driver = Driver
car = ProxyCar
car.drive
driver = Driver
car = ProxyCar
car.drive

Rust


trait ICar
struct Car
impl ICar for Car
impl Car
struct ProxyCar<'a>
impl<'a> ICar for ProxyCar<'a>
impl<'a> ProxyCar<'a>
#
mod tests