Proxy (Unrelated) - vascogrilo/LDE GitHub Wiki

Proxy

Provide a surrogate or placeholder for another object to control access to it.

What it is

It is a design pattern suggested by GoF that aims to provide a surrogate or placeholder for another objecto to control access to it. It is applicable whenever there is a need for a more versatile or sophisticated reference to an object than a simple pointer.

Motivation

One reason for controlling access to an object is to defer the full cost of its creation and initialization until we actually need to use it. Consider a document editor that 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 we should 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 do we put in the document in place of the image? And how can we hide the fact that the image is created on demand so that we don't complicate 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.

Applicability

  • A remote proxy provides a local representative for an object in a different address space. NEXTSTEP[Add94] uses the class NXProxy for this purpose. Coplien[Cop92] calls this kind of proxy an "Ambassador."
  • A virtual proxy creates expensive objects on demand. The ImageProxy described in the Motivation is an example of such a proxy.
  • A protection proxy controls access to the original object. Protection proxies are useful when objects should have different access rights. For example, KernelProxies in the Choices operating system [CIRM93] provide protected access to operating system objects.
  • A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed. Typical uses include
    • counting the number of references to the real object so that it can be freed automatically when there are no more references
    • loading a persistent object into memory when it's first referenced.
    • checking that the real object is locked before it's accessed to ensure that no other object can change it.

Consequences

The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy:

  • A remote proxy can hide the fact that an object resides in a different address space.
  • A virtual proxy can perform optimizations such as creating an object on demand.
  • Both protection proxies and smart references allow additional housekeeping tasks when an object is accessed.

There's another optimization that the Proxy pattern can hide from the client. It's called copy-on-write, and it's related to creation on demand. Copying a large and complicated object can be an expensive operation. If the copy is never modified, then there's no need to incur this cost. By using a proxy to postpone the copying process, we ensure that we pay the price of copying the object only if it's modified.

To make copy-on-write work, the subject must be reference counted. Copying the proxy will do nothing more than increment this reference count. Only when the client requests an operation that modifies the subject does the proxy actually copy it. In that case the proxy must also decrement the subject's reference count. When the reference count goes to zero, the subject gets deleted.
Copy-on-write can reduce the cost of copying heavyweight subjects significantly.

Structure

Proxy Pattern Structure


Name

Proxy

Context I

Sometimes a client object may not be able to access a service provider object (also referred to as a target object) by normal means. This could happen for a variety of reasons depending on:

  • The location of the target object
    The target object may be present in a different address space in the same or a different computer.
  • The state of existence of the target object
    The target object may not exist until it is actually needed to render a service or the object may be in a compressed form.
  • Special Behavior
    The target object may offer or deny services based on the access privileges of its client objects. Some service provider objects may need special consideration when used in a multithreaded environment.

In such cases, the Proxy pattern suggests using a separate object referred to as a proxy to provide a means for different client objects to access the target object in a normal, straightforward manner.

  • The Proxy object offers the same interface as the target object.
  • The Proxy object interacts with the target object on behalf of a client object and takes care of the specific details of communicating with the target object.
  • Client objects need not even know that they are dealing with Proxy for the original object.
  • Proxy object serves as a transparent bridge between the client and an inaccessible remote object or an object whose instantiation may have been deferred.

Context II

  • Remote Proxy
    You have a remote object and you want the client to be transparent to the fact that it is a remote object and make calls as if it were a local object. This could involve transforming the call stack to a wire representation and back. A good example of this is Remoting or web service calls or even the good old DCOM calls.
  • Virtual Proxy
    Or you have a requirement to lazy load an object only when it is needed, some features of the actual object could be mimicked while some of them require the actual object. A typical example is that of a Word processing application. The document load times need to be significantly low. The document if it has embedded images and we try to load them as well then it could take time. So instead of the actual image we can have a proxy which just displays an empty rectangle. As we navigate to the specific page or after the document is loaded we can load the actual image object.
  • Protection Proxy
    There’s yet another proxy category which protects are guards access to a specific object, this is called a protection proxy.
  • Logging Proxy
    Logs all calls to the method of the BaseBehavior class, either before or after the BaseBehavior, or both.
  • Perfecting Proxy
    Ensure that all usage of the BaseBehavior class is correct, perfecting that usage as needed before delegating to the BaseBehavior class. For example, when an API requires a parameter is below x, a perfection proxy would reduce that parameter to x if it were too high, then delegate to the BaseBehavior class with the perfected value.
  • Cache Proxy
    The Proxy adds caching behavior to an object that represents a data source.

Problem

Solution

Consequences

The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy:

  • A remote proxy can hide the fact that an object resides in a different address space.
  • A virtual proxy can perform optimizations such as creating an object on demand.
  • Both protection proxies and smart references allow additional housekeeping tasks when an object is accessed.

There's another optimization that the Proxy pattern can hide from the client. It's called copy-on-write, and it's related to creation on demand. Copying a large and complicated object can be an expensive operation. If the copy is never modified, then there's no need to incur this cost. By using a proxy to postpone the copying process, we ensure that we pay the price of copying the object only if it's modified.

To make copy-on-write work, the subject must be reference counted. Copying the proxy will do nothing more than increment this reference count. Only when the client requests an operation that modifies the subject does the proxy actually copy it. In that case the proxy must also decrement the subject's reference count. When the reference count goes to zero, the subject gets deleted.
Copy-on-write can reduce the cost of copying heavyweight subjects significantly.

  • Proxies promote strong cohesion.
  • Proxies simplify the client object and the object being proxied (by hiding complex issues like remoting and caching, etc…)
  • If the instantiation of all classes is encapsulated by policy, inserting a proxy at a later time is significantly easier.
  • Proxies often evolve into Decorators when multiple additional behaviors are needed. Knowing this, one does not have to introduce the Decorator until it is needed, avoiding overdesign and analysis paralysis.