-----------------------------------------------------------------------------
[Proxy]
의도:
다른 객체에 접근하기 위해 중간 대리 역활을 하는 객체를 둔다.
다른 이름:
Surrogate
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Proxy
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <list>
#include <algorithm>
#define USE_HANDLE 1
#if (USE_HANDLE==1)
/////////////////////////////////////////////////////////////////////////////
//
// Handle
//
/////////////////////////////////////////////////////////////////////////////
template<typename T>
class CRefCountedInstance
{
public:
CRefCountedInstance ();
public:
inline void AddRef (void);
inline void Release (void);
inline void Assign (T *p);
inline bool IsReferenced (void);
inline T* GetInstance (void);
private:
T *Instance_;
int RefCount_;
};
template<typename T>
CRefCountedInstance<T>::CRefCountedInstance () :
RefCount_ (0),
Instance_ (0)
{
}
template<typename T>
void CRefCountedInstance<T>::AddRef (void)
{
RefCount_++;
}
template<typename T>
void CRefCountedInstance<T>::Release (void)
{
if (RefCount_>0)
{
RefCount_--;
}
if (RefCount_==0)
{
if (Instance_)
{
delete Instance_;
}
Instance_ = 0;
}
}
template<typename T>
void CRefCountedInstance<T>::Assign (T *p)
{
Instance_ = p;
AddRef ();
}
template<typename T>
bool CRefCountedInstance<T>::IsReferenced (void)
{
if (RefCount_==0)
return false;
return true;
}
template<typename T>
T* CRefCountedInstance<T>::GetInstance (void)
{
return Instance_;
}
template<typename T>
class Handle
{
public:
Handle ();
explicit Handle (T *p);
Handle (const Handle<T> ©);
virtual ~Handle ();
public:
Handle<T>& operator = (const Handle<T>& rhs);
public:
inline T& operator* () const;
inline T* operator-> () const;
inline T* Get (void) const;
private:
CRefCountedInstance<T>* Rep_;
};
template<typename T>
Handle<T>::Handle () : Rep_(0)
{
}
template<typename T>
Handle<T>::Handle (T *p)
{
Rep_ = new CRefCountedInstance<T>();
Rep_->Assign(p);
}
template<typename T>
Handle<T>::Handle (const Handle<T> ©)
{
Rep_ = copy.Rep_;
if (Rep_)
Rep_->AddRef ();
}
template<typename T>
Handle<T>::~Handle ()
{
if (Rep_)
{
Rep_->Release ();
if (!Rep_->IsReferenced())
delete Rep_;
}
}
template<typename T>
Handle<T>& Handle<T>::operator = (const Handle<T>& rhs)
{
if (this == &rhs) return *this;
if (Rep_)
Rep_->Release ();
Rep_ = rhs.Rep_;
if (Rep_)
Rep_->AddRef ();
return *this;
}
template<typename T>
T& Handle<T>::operator*() const
{
return *(Rep_->GetInstance());
}
template<typename T>
T* Handle<T>::operator -> () const
{
if (Rep_==0)
return 0;
return (Rep_->GetInstance());
}
template<typename T>
T* Handle<T>::Get (void) const
{
if (Rep_==0)
return 0;
return (Rep_->GetInstance());
}
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Proxy
//
/////////////////////////////////////////////////////////////////////////////
class Subject
{
public:
virtual ~Subject() {}
public:
virtual void Request (void) = 0;
virtual void SetData (int ) = 0;
};
class RealSubject : public Subject
{
public:
explicit RealSubject (int n) :
Data_ (n)
{
std::cout << "RealSubject::RealSubject(" << Data_ << ")" << std::endl;
}
virtual ~RealSubject ()
{
std::cout << "RealSubject::~RealSubject(" << Data_ << ")" << std::endl;
}
public:
virtual void Request (void)
{
std::cout << "RealSubject::Request(): Data_ = " << Data_ << std::endl;
}
virtual void SetData (int n)
{
Data_ = n;
}
private:
int Data_;
};
#if (USE_HANDLE==1)
class Proxy :
public Subject
{
public:
Proxy() : SubjectData_(0)
{
}
explicit Proxy (int n) :
SubjectData_ (n)
{
}
Proxy (const Proxy ©)
{
const_cast<Proxy&>(copy).Load();
SubjectData_ = copy.SubjectData_;
Subject_ = copy.Subject_;
}
virtual ~Proxy () {}
public:
virtual void Request (void)
{
GetSubject()->Request();
}
virtual void SetData (int n)
{
GetSubject()->SetData(n);
}
private:
Subject* GetSubject (void)
{
if (Subject_.Get()==0)
{
Handle<Subject> s ( new RealSubject(SubjectData_) );
Subject_ = s;
}
return Subject_.Get();
}
public:
void Load (void)
{
GetSubject();
}
public:
Proxy& operator = (const Proxy& rhs)
{
if (this == &rhs) return *this;
const_cast<Proxy&>(rhs).Load();
SubjectData_ = rhs.SubjectData_;
Subject_ = rhs.Subject_;
return *this;
}
private:
Handle<Subject> Subject_;
int SubjectData_;
};
#else
class Proxy :
public Subject
{
public:
Proxy() :
SubjectData_(0),
Subject_ (0)
{
}
explicit Proxy (int n) :
SubjectData_ (n),
Subject_ (0)
{
}
virtual ~Proxy ()
{
if (Subject_)
delete Subject_;
}
public:
virtual void Request (void)
{
GetSubject()->Request();
}
virtual void SetData (int n)
{
GetSubject()->SetData(n);
}
private:
Subject* GetSubject (void)
{
if (Subject_==0)
{
Subject_ = new RealSubject(SubjectData_);
}
return Subject_;
}
private:
Subject *Subject_;
int SubjectData_;
};
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
#if (USE_HANDLE==1)
std::cout << "(USE_HANDLE==1)" << std::endl << std::endl;
Proxy a(1);
Proxy b;
Proxy c;
std::cout << "a.Load();" << std::endl;
//a.Load();
std::cout << std::endl;
std::cout << "b=a;" << std::endl;
b=a;
std::cout << std::endl;
std::cout << "a.Request ();" << std::endl;
a.Request ();
std::cout << std::endl;
std::cout << "a.SetData (2);" << std::endl;
a.SetData (2);
std::cout << std::endl;
std::cout << "b.Request ();" << std::endl;
b.Request ();
std::cout << std::endl;
std::cout << "c=a" << std::endl;
c=a;
std::cout << "c.Request()" << std::endl;
c.Request ();
std::cout << std::endl;
#else
std::cout << "(USE_HANDLE==0)" << std::endl << std::endl;
Proxy a(1);
RealSubject b(2);
std::cout << std::endl;
std::cout << "a.Request()" << std::endl;
a.Request (); // late creating instance
std::cout << std::endl;
std::cout << "a.Request()" << std::endl;
b.Request ();
std::cout << std::endl;
#endif
return 0;
}
-----------------------------------------------------------------------------
(USE_HANDLE==1)
a.Load();
RealSubject::RealSubject(1)
b=a;
a.Request ();
RealSubject::Request(): Data_ = 1
a.SetData (2);
b.Request ();
RealSubject::Request(): Data_ = 2
c=a
c.Request()
RealSubject::Request(): Data_ = 2
RealSubject::~RealSubject(2)
-----------------------------------------------------------------------------
(USE_HANDLE==0)
RealSubject::RealSubject(2)
a.Request()
RealSubject::RealSubject(1)
RealSubject::Request(): Data_ = 1
a.Request()
RealSubject::Request(): Data_ = 2
RealSubject::~RealSubject(2)
RealSubject::~RealSubject(1)