Applied Design Patterns with Java
Structural :: Proxy (207) {C ch 15}
Intent
Provide a surrogate or placeholder for another object to control
access to it.
Motivation
One reason for controlling access to an object is to defer
the full cost of its creation and initialization until actually needed. A document editor can embed graphical objects
in a document. Some graphical objects, like large raster images, can be expensive to create. But opening a document
should be fast, so it's best to avoid creating all the expensive objects at once when the document is opened. This
isn't necessary anyway, because not all of these objects will be visible in the document at the same time. These
constraints would suggest creating each expensive object on demand, which in this case occurs when an image becomes
visible. But what is put in the document in place of the image? And how is the fact that the image is created on
demand hidden, without complicating the editor's implementation? This optimization shouldn't impact the rendering
and formatting code, for example. The solution is to use another object, an image Proxy, that acts as a stand-in
for the real image. The Proxy acts just like the image and takes care of instantiating it when
it's required.
The image Proxy creates the real image only when the document editor asks it to display itself by invoking
its Draw operation. The Proxy forwards subsequent requests directly to the image. It must therefore
keep a reference to the image after creating it. Assume that images are stored in separate files. In this case,
use the file name as the reference to the real object. The Proxy also stores its extent, that is, its width and height. The extent
lets the proxy respond to requests for its size from the formatter without actually instantiating the image. The
following class diagram illustrates this example in more detail.
The document editor accesses embedded images through the interface defined
by the abstract Graphic class. ImageProxy is a class for images that are created on demand. ImageProxy maintains the file
name as a reference to the image on disk. The file name is passed as an argument to the ImageProxy constructor.
ImageProxy
also stores the bounding box of the image and a reference to the real Image instance. This reference won't be valid
until the Proxy
instantiates the real image. The Draw() operation makes sure the image is instantiated before forwarding it the
request. GetExtent() forwards the request to the image only if it's instantiated; otherwise ImageProxy returns the extent
it stores.