구조패턴-Flyweight

2008. 8. 19. 00:28 from 셈말짓기/GoF

-----------------------------------------------------------------------------
[Flyweight]
의도:
대규모의 미세한 객체들을 효과적으로 사용하기 위해서는 공유 개념을 도입
-----------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////
//
// A Structural part of GoF's Design Patterns
//
// - Flyweight
//
/////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <tchar.h>

#include <iostream>
#include <memory>
#include <map>
#include <string>
#include <list>
#include <algorithm>


/////////////////////////////////////////////////////////////////////////////
//
// Flyweight
//
/////////////////////////////////////////////////////////////////////////////
class Flyweight
{
public:
 virtual ~Flyweight() {}
public:
 virtual void Operation (void) = 0;
};

class ConcreteFlyweight : public Flyweight
{
public:
 ConcreteFlyweight (std::string s, int n) :
  Key_   (n),
  Value_ (s)
 {
 }

public:
 virtual void Operation (void)
 {
  std::cout << Value_.c_str() << "(" << Key_ << ")" << std::endl;
 }

private:
 int         Key_;
 std::string Value_;
};

class UnsharedConcreteFlyweight : public Flyweight
{
public:
 UnsharedConcreteFlyweight (std::string s) :
  Value_ (s)
 {
 }

public:
 virtual void Operation (void)
 {
  std::cout << Value_.c_str() << std::endl;
 }

private:
 std::string Value_;
};

//// ------------------------------------------------------------------------

class FlyweightFactory
{
private:
 struct PoolDeleter
 {
 public:
  PoolDeleter() : Count_(0) {}
 public:
  void operator()(std::pair<int,Flyweight*> i)
  {
   Flyweight *p = i.second;

   if (p)
   {
    Count_++;
    delete p;
   }
  }
  operator int ()
  {
   return Count_;
  }
 private:
  int Count_;
 };

public:
 virtual ~FlyweightFactory ()
 {
  int Count;

  Count = std::for_each(Pool_.begin(), Pool_.end(), PoolDeleter());
  std::cout << "~FlyweightFactory(): [ConcreteFlyweight] deleting count="
            << Count
            << std::endl
            << std::endl;
 }

public:
 Flyweight* GetFlyweight (std::string value, int key)
 {
  Flyweight*  f;

  if ( Pool_.end() == Pool_.find (key) )
  {
   f = new ConcreteFlyweight (value, key);
   Pool_[key] = f;
  }
  else
  {
   f = Pool_[key];
  }

  return f;
 }

 Flyweight* GetUnsharedFlyweight (std::string value)
 {
  Flyweight* f;

  f = new UnsharedConcreteFlyweight ( value );

  return f;
 }

private:
 std::map <int,Flyweight*> Pool_;
};

//// ------------------------------------------------------------------------

class Context
{
private:
 template<class T>
 struct OperationCaller : public std::unary_function<T, void>
 {
 public:
  void operator()(T ptr)
  {
   if (ptr)
    ptr->Operation();
  }
 };

 template<class T>
 struct ListDeleter : public std::unary_function<T, void>
 {
 public:
  ListDeleter() : Count_(0) {}
 public:
  void operator()(T ptr)
  {
   if (ptr)
   {
    if (dynamic_cast<UnsharedConcreteFlyweight*>(ptr))
    {
     Count_++;
     delete ptr;
    }
   }
  }
  operator int ()
  {
   return Count_;
  }
 private:
  int Count_;
 };

public:
 ~Context ()
 {
  int Count;

  Count = std::for_each(List_.begin(), List_.end(), ListDeleter<Flyweight*>());
  std::cout << "~Context(): [UnsharedConcreteFlyweight] deleting count="
            << Count
            << std::endl;
 }

public:
 void Add (std::string s, int n=0)
 {
  if (n)
   List_.push_back ( Factory_.GetFlyweight (s, n) );
  else
   List_.push_back ( Factory_.GetUnsharedFlyweight (s) );
 }

 void Operation (void)
 {
  std::for_each(List_.begin(), List_.end(), OperationCaller<Flyweight*>());  

  std::cout << std::endl;
 }

private:
 std::list<Flyweight*> List_;
 FlyweightFactory      Factory_;
};


/////////////////////////////////////////////////////////////////////////////
//
// Startup
//
/////////////////////////////////////////////////////////////////////////////
int _tmain(int argc, _TCHAR* argv[])
{
 Context context;

 context.Add ("one", 1);
 context.Add ("two"   );
 context.Add ("one", 1);
 context.Add ("two"   );
 context.Add ("one", 1);
 context.Add ("two"   );
 context.Add ("one", 1);
 context.Add ("two"   );
 context.Add ("one", 1);
 context.Add ("two"   );

 context.Operation ();

 return 0;
}
-----------------------------------------------------------------------------
one(1)
two
one(1)
two
one(1)
two
one(1)
two
one(1)
two

~Context(): [UnsharedConcreteFlyweight] deleting count=5
~FlyweightFactory(): [ConcreteFlyweight] deleting count=1


Posted by 셈말짓기 :