구조패턴-Proxy

2008. 8. 19. 16:04 from 셈말짓기/GoF

-----------------------------------------------------------------------------
[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> &copy);
 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> &copy)
{
 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 &copy)
 {
  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)

Posted by 셈말짓기 :