//
Purpose.  Direct coupling, lots of
start-up and shut-down overhead
#include <iostream>
#include
<string>
using namespace std;
class Image {
   int       
id;
   static int
next;
public:
   Image() { id
= next++;  cout << "   $$ ctor: "<< id << '\n';
}
   ~Image()              { cout << "   dtor: " << id << '\n';
}
   void draw()           { cout << "   drawing image " << id <<
'\n'; }
};
int Image::next = 1;
void main( void ) {
   Image images[5];
   int  
i;
   cout <<
"Exit[0], Image[1-5]: ";
  
cin >> i;
   while (i)
{
      images[i-1].draw();
      cout << "Exit[0], Image[1-5]:
";
      cin >> i;
}  }
//    $$ 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
//
Purpose.  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 RealImage {
  
int  id;
public:
   RealImage( int i ) { id = i;  cout << "   $$ ctor: "<< id << '\n';
}
   ~RealImage()                { cout << "   dtor: " << id << '\n';
}
   void draw()                 { cout << "   drawing image " << 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*
theRealThing;
   int        id;
   static int next;
public:
   Image()  { id =
next++;  theRealThing = 0; }  // 3. Initialized to null
   ~Image() { delete theRealThing; }
   void draw() {
      // 4. When a request comes in, the real
object is created "on first use"
      if ( ! theRealThing) theRealThing = new RealImage( id
);
      // 5. The request is
always delegated
     
theRealThing->draw();
} 
};
int Image::next = 1;
void main( void ) {
   Image images[5];
   int  
i;
   cout <<
"Exit[0], Image[1-5]: ";
  
cin >> i;
   while (i)
{
      images[i-1].draw();
      cout << "Exit[0], Image[1-5]:
";
      cin >> i;
}  }
// 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]: 4
//    drawing image 4
// Exit[0],
Image[1-5]: 0
//    dtor: 4
//    dtor: 2
//
Purpose.  "->" and
"." operators give different results
class Subject {
public: virtual void execute() = 0; };
class RealSubject : public
Subject {
   string str;
public:
   RealSubject( string s ) { str = s; }
   /*virtual*/ void execute() { cout <<
str << '\n'; }
};
class ProxySubject : public Subject
{
   string       first, second, third;
   RealSubject* ptr;
public:
   ProxySubject( string s ) {
      int num = s.find_first_of( ' ' );
      first = s.substr( 0, num );   s = s.substr( num+1 );
      num = s.find_first_of( ' ' );
      second = s.substr( 0, num );  s = s.substr( num+1 );
      num = s.find_first_of( ' ' );
      third = s.substr( 0, num );   s = s.substr( num+1 );
      ptr = new RealSubject( s );
   }
  
~ProxySubject() { delete ptr; }
  
RealSubject* operator->() {
      cout << first << ' ' << second << '
';
      return ptr;
   }
  
/*virtual*/ void execute() {
     
cout << first << ' ' << third << ' ';
      ptr->execute();
   }
};
void main( void )
{
   ProxySubject obj( string(
"the quick brown fox jumped over the dog" ) );
   obj->execute();
   obj.execute();
}
// the
quick fox jumped over the dog
// the brown fox jumped over the dog
//
Purpose.  "A protection proxy
controls access to the original object."
class Person {
   string nameString;
   static string list[];
   static int next;
public:
   Person() { nameString = list[next++];
}
   string name() { return
nameString; }
};
string Person::list[] = { "Tom", "Dick",
"Harry", "Bubba" };
int    Person::next = 0;
class PettyCashProtected {
   int balance;
public:
   PettyCashProtected() { balance = 500;
}
   bool withdraw( int amount )
{
      if (amount > balance)
return false;
      balance -=
amount;
      return true;
   }
  
int getBalance() { return balance; }
};
class PettyCash
{
   PettyCashProtected
realThing;
public:
   bool
withdraw( Person& p, int amount ) {
      if (p.name() == "Tom" || p.name() ==
"Harry" || p.name() == "Bubba")
         return realThing.withdraw( amount
);
      else return false;
   }
  
int getBalance() { return realThing.getBalance(); }
};
void
main( void ) {
   PettyCash  pc;
  
Person     workers[4];
   for (int i=0, amount=100; i < 4; i++,
amount += 100)
      if ( !
pc.withdraw( workers[i], amount ))
         cout << "No money for " <<
workers[i].name() << '\n';
     
else
         cout <<
amount << " dollars for " << workers[i].name() <<
'\n';
   cout <<
"Remaining balance is " << pc.getBalance() << '\n';
}
//
100 dollars for Tom
// No money for Dick
// 300 dollars for
Harry
// No money for Bubba
// Remaining balance is 100
//
Purpose.  Simulate a Persistent Object
Pointer
template <typename TBD>
class POP {          // Persistent Object Pointer
   string oid;
   TBD*   ptr;
public:
   POP( string id )  { oid = id;  ptr = 0;
}
   ~POP()            { delete ptr; }
   TBD* operator->() {
      if ( ! ptr)
         // simulate the persistence
mechanism
         ptr = new TBD(
oid );
      return ptr;
}  };
class Person {
   string name;
  
int    age;
public:
   Person( string n ) { name = n; }
   string getName()   { return name; }
  
int    getAge()    { return 32; }
};
void
main( void ) {
   POP<Person>
ph( "Tom" );
   cout
<< "policy holder is " << ph->getName() <<
", age is " << ph->getAge() << '\n';
}
//
policy holder is Tom, age is 32