Proxy in C++

Why read if you can watch?

Watch Proxy's video tutorial
read full article

Before and after

BEFORE - TDirect coupling, lots of start-up and shut-down overhead.

class Image
{
int m_id;
static int s_next;
public:
Image()
{
m_id = s_next++;
cout << " $$ ctor: " << m_id << '\n';
}
~Image()
{
cout << " dtor: " << m_id << '\n';
}
void draw()
{
cout << " drawing image " << m_id << '\n';
}
};
int Image::s_next = 1;

int main(void)
{
Image images[5];

for (int i; true;)
{
cout << "Exit[0], Image[1-5]: ";
cin >> i;
if (i == 0)
break;
images[i - 1].draw();
}
}

$$ ctor: 1 $$ ctor: 2 $$ ctor: 3 $$ ctor: 4 $$ ctor: 5 Exit[0], Image[1-5]: 2 drawing image 2 Exit[0], Image[1-5]: 4 drawing image 4 Exit[0], Image[1-5]: 2 drawing image 2 Exit[0], Image[1-5]: 0 dtor: 5 dtor: 4 dtor: 3 dtor: 2 dtor: 1


AFTER - Initialization on first use

  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 RealImage
{
int m_id;
public:
RealImage(int i)
{
m_id = i;
cout << " $$ ctor: " << m_id << '\n';
}
~RealImage()
{
cout << " dtor: " << m_id << '\n';
}
void draw()
{
cout << " drawing image " << m_id << '\n';
}
};

// 1. Design an "extra level of indirection" wrapper class
class Image
{
// 2. The wrapper class holds a pointer to the real class
RealImage *m_the_real_thing;
int m_id;
static int s_next;
public:
Image()
{
m_id = s_next++;
// 3. Initialized to null
m_the_real_thing = 0;
}
~Image()
{
delete m_the_real_thing;
}
void draw()
{
// 4. When a request comes in, the real object is
// created "on first use"
if (!m_the_real_thing)
m_the_real_thing = new RealImage(m_id);
// 5. The request is always delegated
m_the_real_thing->draw();
}
};
int Image::s_next = 1;

int main(void)
{
Image images[5];

for (int i; true;)
{
cout << "Exit[0], Image[1-5]: ";
cin >> i;
if (i == 0)
break;
images[i - 1].draw();
}
}

Exit[0], Image[1-5]: 2 $$ ctor: 2 drawing image 2 Exit[0], Image[1-5]: 4 $$ ctor: 4 drawing image 4 Exit[0], Image[1-5]: 2 drawing image 2 Exit[0], Image[1-5]: 0 dtor: 4 dtor: 2