//
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