MohamedG's Log

TW9oYW1lZCBFbC1HZWlzaA==

Proxy Design Pattern

One of the useful design patterns is the proxy design pattern, it allows you to control access to an object via a proxy and also saves you the startup and cleanup overheads as you instantiate only what you use upon request (lazy initialization). Take a look at the following example:


#include<iostream>


#include<string>


 


using namespace std;


 


class Base { // Interface


public:


    virtual string run() = 0;


};


 


class Worker : public Base {


public:


    string run() { return “Worker”; }


};


 


class Proxy : public Base {


private:


    Worker* ptr;


 


    Worker* getWorker() { return ptr ? ptr : (ptr = new Worker()); }


 


public:


    Proxy() : ptr(NULL) {}


    string run() { return getWorker()->run() + ” via Proxy”; }


    Worker * operator->() { return getWorker(); }


};


 


int main() {


    Proxy obj;


 


    cout << obj.run() << endl;  // Worker via Proxy


    cout << obj->run() << endl; // Worker


}


 


There are some points we need to note about the example. There’s an extra layer (one more class) that you need to add to be the proxy/controller. This proxy has a pointer to the actual worker object, it’s initialized to null and only instantiated upon request. That request is to be delegated to the worker to be processed while the proxy can add some logic such as pre-processing or post-processing, but it doesn’t have to because its main goal is to instantiate the worker object upon request. Using this pattern saves you the overhead of construction and destruction. Let’s assume that we have an array of 100 items, this will call the constructor 100 times and will call the destructor 100 times even if you didn’t use them. Using a proxy, you only create the object when it’s used, however there’s a slight overhead by doing that check every time you use it (whether it’s NULL or not), so it’s recommended to just create the objects and drop the check if you know that all of them are going to be used.