Tuesday, 17 February 2015

Proxy Design Pattern with example

Proxy Design Pattern with examples:

The proxy pattern is the one of the design pattern. This is anything that signifies the network connection, a large object in the memory etc.

What is Proxy?
Proxy means that the object represents like another object or in other words, it provides the replacement for another object to control access to it.

Where the proxy pattern used?
The proxy patterns are used where multiple copies of the objects exist. For example there is one complex class needs to be used in many places, using the multiple proxy objects we can access the single complex class object reference. That is all the proxy class objects are forwarded to the one complex class object. The memory for the complex class object gets deleted after all the proxy objects are out of scope.
proxy design pattern

Quick understanding of the above diagram:
 Both the Proxy and the Benz implement the MyICar interface. This allows any client to treat the Proxy just like the Benz.

The Benz is usually the object that does most of the real work; the Proxy controls access to it.
The control may be needed if the MyICar is running on a remote machine, if the MyICar is expensive to create in some way or if access to the MyICar needs to be protected in some way.
The Proxy often instantiates or handle the creation of the Benz.
The Proxy keeps a reference (pointer) to the MyICar, so it can forward requests to the MyICar when necessary.
In some cases, the Proxy may be responsible for creating and destroying the Benz. Clients interact with the Benz through the Proxy.

Example for the proxy pattern:
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
using namespace std;
class MyICar
  virtual void CarInformation() = 0; 

/* Complex class */
class Santro : public MyICar {
  Santro ()
    { }
  void CarInformation () { 
     cout << "I am in the Santro class"<<endl;
class Audi  : public MyICar {
  Audi ()
    { }
  void CarInformation () { 
     cout << "I am in the Audi class"<<endl;

class Benz  : public MyICar {
  Benz ()
    { }
  void CarInformation () { 
     cout << "I am in the Benz class" <<endl;

class Proxy : public MyICar {
  MyICar* m_pcICar;
  Proxy (MyICar* pICar) : m_pcICar (pICar) {}
  void CarInformation () { 
      m_pcICar->CarInformation ();

int main ()
 /* calling the Audi class */
 MyICar *pcIcar = new Audi;
 Proxy ocProxy (pcIcar);
 ocProxy.CarInformation ();

 /* calling the Benz class */
 MyICar *pcIcar1 = new Benz;
 Proxy ocProxy1 (pcIcar1);
 ocProxy1.CarInformation ();

 /* calling the Santro class */
 MyICar *pcIcar2 = new Santro;
 Proxy ocProxy2 (pcIcar2);
 ocProxy2.CarInformation ();
 getchar ();
 return 0;
The output of the above program is:
I am in the Audi class

I am in the Benz class

I am in the Santro class

What are the uses of the proxy pattern?
Proxy patterns are used in multiple places as shown below.
This patterns provide the
 A Proxy provides an interface that forwards function calls to another interface of the same form. A Proxy pattern is useful to modify the behavior of the Benz class while still preserving its interface. This is particularly useful if the Benz class is in third-party library and hence not easily modifiable directly.

There are other use cases of Proxy:

Implement lazy instantiation of the Benz object
In this case, the Benz object is not actually instantiated until a method call is invoked. This can be useful if instantiating the Benz object is a heavyweight operation that we wish to defer until absolutely necessary.

Implement access control to the Benz object
We may want to insert a permissions layer between the Proxy and the Benz objects to ensure that users can only call certain methods on the Benz object if they have appropriate permission.

Support debug or dry-run modes
This lets us insert debugging statement into the Proxy methods to log all call to the Benz object or we can stop the forwarding to certain Benz method with a flag to let us call the Proxy in a dry-run mode, such as to turn off writing the object's state to disk.

Make the Benz class to be thread safe
This can be done by adding mutex locking to the methods that are not thread safe. While this may not be the most efficient way to make the underlying class thread safe, it is a useful if we cannot modify the Benz.

Share resources
We could have multiple Proxy objects share the same underlying Benz class. This could be used to implement reference counting, for instance. This is, actually, another design pattern called the Flyweight pattern, where multiple objects share the same underlying data to minimize memory.

Protect against future changes in the Benz class
We anticipate that a dependent library will change in the future so we create a proxy wrapper around that API that directly mimics the current behavior. So, when the library changes later, we can preserve the old interface via our proxy object and simply change its underlying implementation to use the new library methods.

No comments: