1) Imagine you have a class of such nature where one instance of that class requires quite a bit of resources.
2a) Imagine you *may* need to use a lot of instances of this class.
2b) Therefore you *may* need to create a lot of instances of this class.
3a) The naive approach is to create all the instances you *may* need.
3b) Therefore you'll use a heck of a lot of resources.
4) But the client is only interested in a few of the instances you've created.
5) The result is that we took up much more resources then we needed.
This is an example of such an approach:
Code:
#include <iostream>
#include <string>
using namespace std;
class Thing
{
int id;
static int next;
public:
Thing()
{
id = next++;
cout << "ctor: "<< id << endl;
}
~Thing()
{
cout << "dtor: " << id << endl;
}
void do_it()
{
cout << id << " = doing its thing." << endl;
}
};
//--
int Thing::next = 1;
//--
int main( int )
{
Thing MyThing[5];
int i(1);
while (i)
{
cout << "Which Thing should do its thing (0=EXIT)? -> ";
cin >> i;
cin.get();
if(i < 1)
{
break;
}
MyThing[i-1].do_it();
}
return 0;
}
PROBLEM
What if the user needs only 2 of the 5 instances? The other 3 instances are only a waste of resources.
SOLUTION
Instatiate such classes only when the client actually requests them: use a proxy class.
Let the proxy be responsible for the first creation of a resource-demanding class. And no one needs to know (encapsulation).
Example:
Code:
#include <iostream>
#include <string>
using namespace std;
// Proxy Design Pattern
// 1. Design an "extra level of indirection" wrapper class.
// 2. The wrapper class holds a pointer to the real class.
// 3. The pointer is initialized to null.
// 4. When a request comes in, the real object is created "on first use"
// (aka lazy intialization).
// 5. The request is always delegated.
class RealThing
{
int id;
public:
RealThing( int i )
{
id = i;
cout << "ctor: "<< id << '\n';
}
~RealThing()
{
cout << "dtor: " << id << '\n';
}
void do_it()
{
cout << id << " = doing its thing." << endl;
}
};
//-------------------------------------------
// 1. Design an "extra level of indirection" wrapper class.
class Thing
{
// 2. The wrapper class holds a pointer to the real class.
RealThing* theRealThing;
int id;
static int next;
public:
Thing() : theRealThing(0) // 3. Initialized to null.
{
id = next++;
}
~Thing()
{
delete theRealThing;
}
void do_it()
{
// 4. When a request comes in, the real object is created "on first use".
if ( ! theRealThing)
theRealThing = new RealThing( id );
// 5. The request is always delegated
theRealThing->do_it();
}
};
//--
int Thing::next = 1;
//--------------------------------------------
int main( int )
{
Thing MyThing[5];
int i(1);
while (i)
{
cout << "Which Thing should do its thing (0=EXIT)? ->";
cin >> i;
cin.get();
if(i < 1)
{
break;
}
MyThing[i-1].do_it();
}
return 0;
}