When object construction requires more resources than you can afford, systems
slow down and become unresponsive. Systems avoid this using tactics such as
lazy evaluation or loading-on-demand. But this means objects then have two
jobs. They must be the thing they need to be but also the not-yet-realised
versions of themselves.
Other times, an object might have methods requiring the acquisition of
resources, but in hindsight, those specific methods are not necessary to
achieve your goal. For example, if you want to know the size of an image, you
don’t need to load the whole file, only the header. However, adding the
capacity to partially load a file is a new feature not everyone wants.
Or perhaps what you need from the API is a caching mechanism. As you can see,
the Proxy pattern handles quite a few problems.
A Proxy is an object which takes some responsibility away from the concrete
object, the RealSubject. It acts as a stand-in, like an Adapter, but adjusts
behaviour like a Decorator. Instead of modifying the API or adding features,
it intercepts calls directed at the RealSubject and manages the workload and
lifetime of the RealSubject.
A Proxy can respond faster or more cheaply than the complete object it
represents. You can tune it to the client’s needs rather than write for
completeness or correctness. Examples include image placeholders, remote
service proxies, pre-validating before beginning a transaction, quick estimates
or rough versions of the expensive transformations. In image processing, for
example, a Proxy could provide an instantaneous blocky estimate of a radial
blur or a preview of resource-intense filters.
The GoF book mentions four types of proxy:
Remote proxy: a stand-in for some object in another address space,
potentially even on a different host.
Virtual proxy: e.g. the lazy loading image object.
Protection proxy: adding access control to an object.
The smart reference is a proxy for objects like a smart pointer, potentially
with resource reference for load on demand and for mutable state, handling
locking of the object.
A Proxy is one of the best uses of the object-oriented paradigm. Swapping out
a whole set of behaviours for another is possible in non-OO languages, but the
simultaneous change of behaviour and data representation is smoother in OO. A
virtual proxy removes the decision-making process for resource handling,
decoupling the concern of when and how to handle the required system calls. In
most other paradigms, this involves local adjustment to support the feature.
“The RealSubject is not available. How can I help you?”