Proxy clss
Proxy : 대리자.
목적 : 직관적인 연결, 생성과 파괴에 대한 부하 방지
Ex
#include <iostream>
#include <string>
using namespace std;
class Image
{
int id;
static int next;
public:
Image()
{
id = next++;
cout<<" $$ ctor: "<<id<<endl;
}
~Image()
{
cout<<" dtor: "<<id<<endl;
}
void draw()
{
cout<<" drawing image "<<id<<endl;
}
};
int Image::next = 1;
int _tmain(int argc, _TCHAR* argv[])
{
// 잦은 생성 - 5번의 생성자 호출
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;
}
getchar();
return 0;
}
결과
// $$ 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
목적 : Proxy esing 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 initialization)
5. The request is always delegated
Ex
#include <iostream>
#include <string>
using namespace std;
class RealImage
{
int id;
public:
RealImage(int i)
{
id = i;
cout<<" && ctor: "<<id<<endl;
}
~RealImage()
{
cout<<" dtor: "<<id<<endl;
}
void draw()
{
cout<<" drawing image "<<id<<endl;
}
};
// 1. "간접참조의 추가적인 부분"의 랩핑 클래스
class Image
{
// 2. 실제 객체에 대한 포인터
RealImage* theRealThing;
int id;
static int next;
public:
Image()
{
id = next++;
theRealThing = NULL; // 3. null로 초기화
}
~Image()
{
delete theRealThing;
}
void draw()
{
// 4. 요구가 들어올때 실제 객체가 만들어 진다.
if(!theRealThing)
theRealThing = new RealImage(id);
// 5. 요구는 항상 위임되어진다.
theRealThing->draw();
}
};
int Image::next = 1;
int _tmain(int argc, _TCHAR* argv[])
{
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;
}
getchar();
return 0;
}
결과
// 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
결론
아까와는 결과가 확연이 다르다.
중간에 wrapper클래스를 둠으로써 생성자의 호출을 최대한 뒤로 미루게 되었다.
그럼으로써 굳이 생성하지 않아도 될 자원을 생성하는 부하를 막을 수 있었다.
목적 : "->"와 "." 연산자가 다른 결과를 가진다.
Ex
class Subject
{
public:
virtual void execute() = 0;
};
class RealSubject : public Subject
{
string str;
public:
RealSubject(string s)
{
str = s;
}
virtual void execute() // virtual을 붙이든 붙이지 않든 가상함수 테이블은 만들어 지는걸까?
{
cout<<str<<endl;
}
};
class ProxySubject : public Subject
{
string first, second, third;
RealSubject* ptr; // real의 object
public:
ProxySubject(string s)
{
int num = (int)s.find_first_of(' '); // 처음으로 공백이 나오는 위치
first = s.substr(0, num); // 0부터 num 위치까지 카피
s = s.substr(num+1); // 해당위치부터 끝까지 리턴
num = (int)s.find_first_of(' ');
second = s.substr(0, num);
s = s.substr(num+1);
num = (int)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();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
// 2.
ProxySubject obj(string("the quick brown fox jumped over the dog"));
obj->execute();
obj.execute();
getchar();
return 0;
}
결과
// the quick fox jumped over the dog
// the brown fox jumped over the dog
이 예에서는 이전 예제처럼 기다렸다가 real을 생성하는것 외에 다른것을 말하려고 하는것 같다.
즉, 프록시 클래스를 활용하면 클래스 객체에 대한 연산자 오버로딩을 활용할 수 있다는 것인듯.
이 예에서는 "->" 와 "."에 다른 처리를 하고자 프로시클래스에서 "->"연산자를 오버로딩하였다.
목적 : real object에 접근하기 위한 protection proxy 컨트롤들
EX
class Person // 사람들의 목록
{
string nameString;
static string list[];
static int next;
public:
Person()
{
nameString = list[next++];
}
string name()
{
return nameString;
}
};
string Person::list[] = {"AA", "BB", "CC", "DD"};
int Person::next = 0;
class PettyCashProtected // pc에서 접근을 제어해서 관리해야 할 부분. (잔액)
{
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 // pc에서 공개로 사용하는 부분
{
PettyCashProtected realThing; // pc의 비공개에 접근하는 object
public:
bool withdraw(Person& p, int amount)
{
if(p.name() == "AA" || p.name() == "CC" || p.name() == "DD" )
return realThing.withdraw(amount);
else
return false;
}
int getBalance()
{
return realThing.getBalance();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
// 3.
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()<<endl;
else
cout<<amount<<" dollars for "<<workers[i].name()<<endl;
}
cout<<"Remaining balance is "<<pc.getBalance()<<endl;
getchar();
return 0;
}
결과
// 100 dollars for Tom
// No money for Dick
// 300 dollars for Harry
// No money for Bubba
// Remaining balance is 100
결론
이 예에서는 pc의 protected한 클래스를 만들어 두고 이곳에 접근하기 위한 용도로 pc클래스(proxy)를 만든듯 하다.
즉 proxy는 대리자로서 real object에 접근이 가능하다.
목적 : Persistent Object Pointer 인 척 하기
EX
template <typename T> class POP // Persistent Object Pointer
{
string oid;
T* ptr;
public:
POP(string id)
{
oid = id;
ptr = NULL;
}
~POP()
{
delete ptr;
}
T* operator->()
{
if(!ptr)
ptr = new T(oid); //simulate the persistence mechanism
return ptr;
}
};
class Men
{
string name;
int age;
public:
Men(string n)
{
name = n;
}
string getName()
{
return name;
}
int getAge()
{
return 32;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
// 4.
POP<Men> ph("사람a");
cout<<"policy holder is "<<ph->getName()<<", age is "<<ph->getAge()<<endl;
getchar();
return 0;
}
결과
// policy holder is Tom, age is 32
결론
이 예는 확실히 무었을 말하려하는지 잘 와닿지는 않는데...
대략적으로 템플릿클래스를 proxy로 쓰겠다는 말인듯 하다.
나머지 -> 연산자 오버로딩이야 위에서 했으니까.머...
'Study > C++' 카테고리의 다른 글
bitarray 제작, 활용 (0) | 2009.07.20 |
---|---|
bitarray (0) | 2009.07.18 |
디자인 패턴 (0) | 2009.07.16 |
explicit 키워드에 대해서. (0) | 2009.07.14 |
string -> char* -> WCHAR* 타입 변환 (0) | 2009.07.14 |