Design‎ > ‎Design Pattern‎ > ‎Structural Pattern‎ > ‎

Proxy

Intention
- Provide a surrogate or placeholder for another object to control access to it.
- Use an extra level of indirection to support distributed, controlled, or intelligent access.
- Add a wrapper and delegation to protect the real component from undue complexity.
 
 
 
 
 
Application
- A virtual proxy is a placeholder for “expensive to create” objects. The real object is only created when a client first requests/accesses the object.
- A remote proxy provides a local representative for an object that resides in a different address space. This is what the “stub” code in RPC and CORBA provides.
- A protective proxy controls access to a sensitive master object. The “surrogate” object checks that the caller has the access permissions required prior to forwarding the request.
- A smart proxy interposes additional actions when an object is accessed.
  • Counting the number of references to the real object so that it can be freed automatically when there are no more references (aka smart pointer),
  • Loading a persistent object into memory when it’s first referenced,
  • Checking that the real object is locked before it is accessed to ensure that no other object can change it.
 
Checklist
- Identify the leverage or “aspect” that is best implemented as a wrapper or surrogate.
- Define an interface that will make the proxy and the original component interchangeable.
- Consider defining a Factory that can encapsulate the decision of whether a proxy or original object is desirable.
- The wrapper class holds a pointer to the real class and implements the interface.
- The pointer may be initialized at construction, or on first use.
- Each wrapper method contributes its leverage, and delegates to the wrappee object.
 
 
Thumb Rules
- Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.
- Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests.
 
Code
 
#include <iostream>
using namespace std;
class A
{
  public:
  virtual void execute() = 0;
  virtual ~A() {};
};
class RealA : public A
{
public:
  RealA() {cout << "RealA ctor \n";}
  void execute()
  {
    cout << "RealA executed \n";
  }
  ~RealA() {cout << "RealA dtor \n";}
};
#define VALID_ACCESS_ID 123
#define LIMITED_ACCESS_ID 1234
// 1. Design an "extra level of indirection" wrapper class
class ProxyA : public A
{
  int m_accessId;
  RealA *realA;
 
public:
  ProxyA(int accessId)
  {
    m_accessId = accessId;
    // 3. Initialized to null
    realA = NULL;
    cout << "ProxyA ctor \n";
  }
  void execute()
  {
    if(VALID_ACCESS_ID  != m_accessId)
    {
      cout << "Access Denied \n";
      return;
    }
    // 2. The wrapper class holds a pointer to the real class
    if(!realA)
      realA = new RealA();
    realA->execute();
  }
  ~ProxyA()
  {
    if(realA)
      delete realA;
    cout << "ProxyA dtor \n";
  }
};

int main()
{
  A *a1 = new ProxyA(VALID_ACCESS_ID);
  a1->execute();
  delete a1;
 
  A *a2 = new ProxyA(LIMITED_ACCESS_ID);
  a2->execute();
  delete a2;
 
  system("PAUSE");
  return 1;
}


ProxyA ctor
RealA ctor
RealA executed
RealA dtor
ProxyA dtor
ProxyA ctor
Access Denied
ProxyA dtor
Comments