View Single Post
Old 05-03-2005, 12:13 PM   #3 (permalink)
Valmont
[code][/code] enforcer
 
Valmont's Avatar
 
Join Date: Mar 2003
Location: Netherlands
Posts: 1,544
Valmont is on a distinguished road
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;
}
__________________
Valmont is offline   Reply With Quote